aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Driver/ToolChains
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Driver/ToolChains')
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp300
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.h22
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/AMDGPU.cpp461
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/AMDGPU.h40
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp267
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h49
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/AVR.cpp324
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/AVR.h30
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Ananas.cpp144
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Ananas.h65
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/AArch64.cpp298
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/ARM.cpp296
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/ARM.h25
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/CSKY.cpp169
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/CSKY.h47
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp232
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/LoongArch.h37
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/M68k.cpp50
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/M68k.h8
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/Mips.cpp28
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/Mips.h5
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/PPC.cpp140
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/PPC.h5
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.cpp585
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.h4
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/Sparc.cpp157
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/Sparc.h3
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp2
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/VE.cpp8
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/VE.h2
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/X86.cpp136
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/X86.h4
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/BareMetal.cpp425
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/BareMetal.h51
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/CSKYToolChain.cpp204
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/CSKYToolChain.h63
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp3920
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.h52
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/CloudABI.cpp149
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/CloudABI.h70
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.cpp1728
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.h90
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Contiki.cpp27
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Contiki.h39
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/CrossWindows.cpp17
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/CrossWindows.h10
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Cuda.cpp574
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Cuda.h154
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Darwin.cpp1212
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Darwin.h80
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/DragonFly.cpp163
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/DragonFly.h14
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Flang.cpp772
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Flang.h63
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp242
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.h34
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Fuchsia.cpp238
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Fuchsia.h56
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp1558
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.h21
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/HIP.cpp458
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/HIPAMD.cpp434
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/HIPAMD.h (renamed from contrib/llvm-project/clang/lib/Driver/ToolChains/HIP.h)50
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/HIPSPV.cpp288
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/HIPSPV.h102
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/HIPUtility.cpp179
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/HIPUtility.h35
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/HLSL.cpp259
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/HLSL.h63
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Haiku.cpp257
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Haiku.h40
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Hexagon.cpp214
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Hexagon.h20
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Hurd.cpp24
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Lanai.h2
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/LazyDetector.h45
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Linux.cpp261
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Linux.h8
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/MSP430.cpp9
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/MSP430.h6
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/MSVC.cpp953
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/MSVC.h57
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/MSVCSetupApi.h514
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/MinGW.cpp371
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/MinGW.h32
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Minix.cpp113
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Minix.h64
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/MipsLinux.cpp16
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/MipsLinux.h1
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Myriad.cpp293
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Myriad.h103
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/NaCl.cpp11
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/NaCl.h2
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/NetBSD.cpp330
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/NetBSD.h14
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/OHOS.cpp419
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/OHOS.h95
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/OpenBSD.cpp187
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/OpenBSD.h13
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/PPCFreeBSD.cpp28
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/PPCFreeBSD.h33
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/PPCLinux.cpp75
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/PPCLinux.h9
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/PS4CPU.cpp309
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/PS4CPU.h124
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/RISCVToolchain.cpp33
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/RISCVToolchain.h5
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/ROCm.h65
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/SPIRV.cpp93
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/SPIRV.h89
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Solaris.cpp239
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Solaris.h18
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/TCE.cpp4
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/TCE.h2
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/VEToolchain.cpp55
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/VEToolchain.h3
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/WebAssembly.cpp267
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/WebAssembly.h17
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/XCore.cpp11
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/XCore.h7
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/ZOS.cpp308
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/ZOS.h62
122 files changed, 15548 insertions, 8619 deletions
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp
index 3000b8416adf..e6126ff62db3 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp
@@ -12,7 +12,9 @@
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Path.h"
using AIX = clang::driver::toolchains::AIX;
@@ -28,6 +30,7 @@ void aix::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
+ const Driver &D = getToolChain().getDriver();
ArgStringList CmdArgs;
const bool IsArch32Bit = getToolChain().getTriple().isArch32Bit();
@@ -36,6 +39,11 @@ void aix::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
if (!IsArch32Bit && !IsArch64Bit)
llvm_unreachable("Unsupported bit width value.");
+ if (Arg *A = C.getArgs().getLastArg(options::OPT_G)) {
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getSpelling() << D.getTargetTriple();
+ }
+
// Specify the mode in which the as(1) command operates.
if (IsArch32Bit) {
CmdArgs.push_back("-a32");
@@ -74,6 +82,29 @@ void aix::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
Exec, CmdArgs, Inputs, Output));
}
+// Determine whether there are any linker options that supply an export list
+// (or equivalent information about what to export) being sent to the linker.
+static bool hasExportListLinkerOpts(const ArgStringList &CmdArgs) {
+ for (size_t i = 0, Size = CmdArgs.size(); i < Size; ++i) {
+ llvm::StringRef ArgString(CmdArgs[i]);
+
+ if (ArgString.starts_with("-bE:") || ArgString.starts_with("-bexport:") ||
+ ArgString == "-bexpall" || ArgString == "-bexpfull")
+ return true;
+
+ // If we split -b option, check the next opt.
+ if (ArgString == "-b" && i + 1 < Size) {
+ ++i;
+ llvm::StringRef ArgNextString(CmdArgs[i]);
+ if (ArgNextString.starts_with("E:") ||
+ ArgNextString.starts_with("export:") || ArgNextString == "expall" ||
+ ArgNextString == "expfull")
+ return true;
+ }
+ }
+ return false;
+}
+
void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs, const ArgList &Args,
@@ -88,6 +119,11 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (!(IsArch32Bit || IsArch64Bit))
llvm_unreachable("Unsupported bit width value.");
+ if (Arg *A = C.getArgs().getLastArg(options::OPT_G)) {
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getSpelling() << D.getTargetTriple();
+ }
+
// Force static linking when "-static" is present.
if (Args.hasArg(options::OPT_static))
CmdArgs.push_back("-bnso");
@@ -98,6 +134,54 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-bnoentry");
}
+ if (Args.hasFlag(options::OPT_mxcoff_roptr, options::OPT_mno_xcoff_roptr,
+ false)) {
+ if (Args.hasArg(options::OPT_shared))
+ D.Diag(diag::err_roptr_cannot_build_shared);
+
+ // The `-mxcoff-roptr` option places constants in RO sections as much as
+ // possible. Then `-bforceimprw` changes such sections to RW if they contain
+ // imported symbols that need to be resolved.
+ CmdArgs.push_back("-bforceimprw");
+ }
+
+ // PGO instrumentation generates symbols belonging to special sections, and
+ // the linker needs to place all symbols in a particular section together in
+ // memory; the AIX linker does that under an option.
+ if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
+ false) ||
+ Args.hasFlag(options::OPT_fprofile_generate,
+ options::OPT_fno_profile_generate, false) ||
+ 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:ss");
+
+ if (Arg *A =
+ Args.getLastArg(clang::driver::options::OPT_mxcoff_build_id_EQ)) {
+ StringRef BuildId = A->getValue();
+ if (BuildId[0] != '0' || BuildId[1] != 'x' ||
+ BuildId.find_if_not(llvm::isHexDigit, 2) != StringRef::npos)
+ ToolChain.getDriver().Diag(diag::err_drv_unsupported_option_argument)
+ << A->getSpelling() << BuildId;
+ else {
+ std::string LinkerFlag = "-bdbg:ldrinfo:xcoff_binary_id:0x";
+ if (BuildId.size() % 2) // Prepend a 0 if odd number of digits.
+ LinkerFlag += "0";
+ LinkerFlag += BuildId.drop_front(2).lower();
+ CmdArgs.push_back(Args.MakeArgString(LinkerFlag));
+ }
+ }
+
// Specify linker output file.
assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
if (Output.isFilename()) {
@@ -118,19 +202,19 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-bpD:0x110000000");
}
- auto getCrt0Basename = [&Args, IsArch32Bit] {
- // Enable gprofiling when "-pg" is specified.
- if (Args.hasArg(options::OPT_pg))
- return IsArch32Bit ? "gcrt0.o" : "gcrt0_64.o";
- // Enable profiling when "-p" is specified.
- else if (Args.hasArg(options::OPT_p))
- return IsArch32Bit ? "mcrt0.o" : "mcrt0_64.o";
- else
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_shared, options::OPT_r)) {
+ auto getCrt0Basename = [&Args, IsArch32Bit] {
+ if (Arg *A = Args.getLastArgNoClaim(options::OPT_p, options::OPT_pg)) {
+ // Enable gprofiling when "-pg" is specified.
+ if (A->getOption().matches(options::OPT_pg))
+ return IsArch32Bit ? "gcrt0.o" : "gcrt0_64.o";
+ // Enable profiling when "-p" is specified.
+ return IsArch32Bit ? "mcrt0.o" : "mcrt0_64.o";
+ }
return IsArch32Bit ? "crt0.o" : "crt0_64.o";
- };
+ };
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
- options::OPT_shared)) {
CmdArgs.push_back(
Args.MakeArgString(ToolChain.GetFilePath(getCrt0Basename())));
@@ -147,27 +231,109 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// Specify linker input file(s).
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
- // Add directory to library search path.
- Args.AddAllArgs(CmdArgs, options::OPT_L);
- ToolChain.AddFilePathLibArgs(Args, CmdArgs);
- ToolChain.addProfileRTLibs(Args, CmdArgs);
-
- if (getToolChain().ShouldLinkCXXStdlib(Args))
- getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
-
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
- AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
-
- // Support POSIX threads if "-pthreads" or "-pthread" is present.
- if (Args.hasArg(options::OPT_pthreads, options::OPT_pthread))
- CmdArgs.push_back("-lpthreads");
+ if (D.isUsingLTO()) {
+ assert(!Inputs.empty() && "Must have at least one input.");
+ // Find the first filename InputInfo object.
+ auto Input = llvm::find_if(
+ Inputs, [](const InputInfo &II) -> bool { return II.isFilename(); });
+ if (Input == Inputs.end())
+ // For a very rare case, all of the inputs to the linker are
+ // InputArg. If that happens, just use the first InputInfo.
+ Input = Inputs.begin();
+
+ addLTOOptions(ToolChain, Args, CmdArgs, Output, *Input,
+ D.getLTOMode() == LTOK_Thin);
+ }
- if (D.CCCIsCXX())
- CmdArgs.push_back("-lm");
+ if (Args.hasArg(options::OPT_shared) && !hasExportListLinkerOpts(CmdArgs)) {
+
+ const char *CreateExportListExec = Args.MakeArgString(
+ path::parent_path(ToolChain.getDriver().ClangExecutable) +
+ "/llvm-nm");
+ ArgStringList CreateExportCmdArgs;
+
+ std::string CreateExportListPath =
+ C.getDriver().GetTemporaryPath("CreateExportList", "exp");
+ const char *ExportList =
+ C.addTempFile(C.getArgs().MakeArgString(CreateExportListPath));
+
+ for (const auto &II : Inputs)
+ if (II.isFilename())
+ CreateExportCmdArgs.push_back(II.getFilename());
+
+ CreateExportCmdArgs.push_back("--export-symbols");
+ CreateExportCmdArgs.push_back("-X");
+ if (IsArch32Bit) {
+ CreateExportCmdArgs.push_back("32");
+ } else {
+ // Must be 64-bit, otherwise asserted already.
+ CreateExportCmdArgs.push_back("64");
+ }
+
+ auto ExpCommand = std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::None(), CreateExportListExec,
+ CreateExportCmdArgs, Inputs, Output);
+ ExpCommand->setRedirectFiles(
+ {std::nullopt, std::string(ExportList), std::nullopt});
+ C.addCommand(std::move(ExpCommand));
+ CmdArgs.push_back(Args.MakeArgString(llvm::Twine("-bE:") + ExportList));
+ }
- CmdArgs.push_back("-lc");
+ // Add directory to library search path.
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ if (!Args.hasArg(options::OPT_r)) {
+ ToolChain.AddFilePathLibArgs(Args, CmdArgs);
+ ToolChain.addProfileRTLibs(Args, CmdArgs);
+
+ if (getToolChain().ShouldLinkCXXStdlib(Args))
+ getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
+
+ // Add OpenMP runtime if -fopenmp is specified.
+ if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
+ options::OPT_fno_openmp, false)) {
+ switch (ToolChain.getDriver().getOpenMPRuntime(Args)) {
+ case Driver::OMPRT_OMP:
+ CmdArgs.push_back("-lomp");
+ break;
+ case Driver::OMPRT_IOMP5:
+ CmdArgs.push_back("-liomp5");
+ break;
+ case Driver::OMPRT_GOMP:
+ CmdArgs.push_back("-lgomp");
+ break;
+ case Driver::OMPRT_Unknown:
+ // Already diagnosed.
+ break;
+ }
+ }
+
+ // Support POSIX threads if "-pthreads" or "-pthread" is present.
+ if (Args.hasArg(options::OPT_pthreads, options::OPT_pthread))
+ CmdArgs.push_back("-lpthreads");
+
+ if (D.CCCIsCXX())
+ CmdArgs.push_back("-lm");
+
+ CmdArgs.push_back("-lc");
+
+ if (Args.hasArgNoClaim(options::OPT_p, options::OPT_pg)) {
+ CmdArgs.push_back(Args.MakeArgString((llvm::Twine("-L") + D.SysRoot) +
+ "/lib/profiled"));
+ CmdArgs.push_back(Args.MakeArgString((llvm::Twine("-L") + D.SysRoot) +
+ "/usr/lib/profiled"));
+ }
+ }
}
+ if (D.IsFlangMode()) {
+ addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
+ addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
+ CmdArgs.push_back("-lm");
+ CmdArgs.push_back("-lpthread");
+ }
const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
Exec, CmdArgs, Inputs, Output));
@@ -176,6 +342,10 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
/// AIX - AIX tool chain which can call as(1) and ld(1) directly.
AIX::AIX(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: ToolChain(D, Triple, Args) {
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir)
+ getProgramPaths().push_back(getDriver().Dir);
+
ParseInlineAsmUsingAsmParser = Args.hasFlag(
options::OPT_fintegrated_as, options::OPT_fno_integrated_as, true);
getLibraryPaths().push_back(getDriver().SysRoot + "/usr/lib");
@@ -201,11 +371,13 @@ void AIX::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs);
const Driver &D = getDriver();
- // Add the Clang builtin headers (<resource>/include).
if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
SmallString<128> P(D.ResourceDir);
- path::append(P, "/include");
- addSystemInclude(DriverArgs, CC1Args, P.str());
+ // Add the PowerPC intrinsic headers (<resource>/include/ppc_wrappers)
+ path::append(P, "include", "ppc_wrappers");
+ addSystemInclude(DriverArgs, CC1Args, P);
+ // Add the Clang builtin headers (<resource>/include)
+ addSystemInclude(DriverArgs, CC1Args, path::parent_path(P.str()));
}
// Return if -nostdlibinc is specified as a driver option.
@@ -218,20 +390,82 @@ 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++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
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.");
}
+void AIX::addClangTargetOptions(
+ const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadingKind) const {
+ Args.AddLastArg(CC1Args, options::OPT_mignore_xcoff_visibility);
+ Args.AddLastArg(CC1Args, options::OPT_mdefault_visibility_export_mapping_EQ);
+ Args.addOptInFlag(CC1Args, options::OPT_mxcoff_roptr, options::OPT_mno_xcoff_roptr);
+
+ if (Args.hasFlag(options::OPT_fxl_pragma_pack,
+ options::OPT_fno_xl_pragma_pack, true))
+ CC1Args.push_back("-fxl-pragma-pack");
+}
+
+void AIX::addProfileRTLibs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const {
+ if (needsProfileRT(Args)) {
+ // Add linker option -u__llvm_profile_runtime to cause runtime
+ // initialization to occur.
+ CmdArgs.push_back(Args.MakeArgString(
+ Twine("-u", llvm::getInstrProfRuntimeHookVarName())));
+
+ if (const auto *A =
+ Args.getLastArgNoClaim(options::OPT_fprofile_update_EQ)) {
+ StringRef Val = A->getValue();
+ if (Val == "atomic" || Val == "prefer-atomic")
+ CmdArgs.push_back("-latomic");
+ }
+ }
+
+ ToolChain::addProfileRTLibs(Args, CmdArgs);
+}
+
ToolChain::CXXStdlibType AIX::GetDefaultCXXStdlibType() const {
return ToolChain::CST_Libcxx;
}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.h
index d1ec6d10fb3a..755d87e07ec5 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.h
@@ -16,10 +16,10 @@ namespace clang {
namespace driver {
namespace tools {
-/// aix -- Directly call system default assembler and linker.
+/// Directly call system default assembler and linker.
namespace aix {
-class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
+class LLVM_LIBRARY_VISIBILITY Assembler final : public Tool {
public:
Assembler(const ToolChain &TC) : Tool("aix::Assembler", "assembler", TC) {}
@@ -31,7 +31,7 @@ public:
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
public:
Linker(const ToolChain &TC) : Tool("aix::Linker", "linker", TC) {}
@@ -63,16 +63,30 @@ 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; }
+ bool HasNativeLLVMSupport() 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;
+ void addClangTargetOptions(
+ const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadingKind) const override;
+
+ void addProfileRTLibs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+
CXXStdlibType GetDefaultCXXStdlibType() const override;
RuntimeLibType GetDefaultRuntimeLibType() const override;
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/AMDGPU.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/AMDGPU.cpp
index 4a7413112b55..b3c9d5908654 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/AMDGPU.cpp
@@ -9,20 +9,22 @@
#include "AMDGPU.h"
#include "CommonArgs.h"
#include "clang/Basic/TargetID.h"
+#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Options.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/Error.h"
-#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
#include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/TargetParser/Host.h"
+#include <optional>
#include <system_error>
-#define AMDGPU_ARCH_PROGRAM_NAME "amdgpu-arch"
-
using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang::driver::toolchains;
@@ -47,7 +49,7 @@ RocmInstallationDetector::findSPACKPackage(const Candidate &Cand,
FileEnd;
File != FileEnd && !EC; File.increment(EC)) {
llvm::StringRef FileName = llvm::sys::path::filename(File->path());
- if (FileName.startswith(Prefix)) {
+ if (FileName.starts_with(Prefix)) {
SubDirs.push_back(FileName);
if (SubDirs.size() > 1)
break;
@@ -82,15 +84,16 @@ void RocmInstallationDetector::scanLibDevicePath(llvm::StringRef Path) {
!EC && LI != LE; LI = LI.increment(EC)) {
StringRef FilePath = LI->path();
StringRef FileName = llvm::sys::path::filename(FilePath);
- if (!FileName.endswith(Suffix))
+ if (!FileName.ends_with(Suffix))
continue;
StringRef BaseName;
- if (FileName.endswith(Suffix2))
+ if (FileName.ends_with(Suffix2))
BaseName = FileName.drop_back(Suffix2.size());
- else if (FileName.endswith(Suffix))
+ else if (FileName.ends_with(Suffix))
BaseName = FileName.drop_back(Suffix.size());
+ const StringRef ABIVersionPrefix = "oclc_abi_version_";
if (BaseName == "ocml") {
OCML = FilePath;
} else if (BaseName == "ockl") {
@@ -121,11 +124,17 @@ void RocmInstallationDetector::scanLibDevicePath(llvm::StringRef Path) {
WavefrontSize64.On = FilePath;
} else if (BaseName == "oclc_wavefrontsize64_off") {
WavefrontSize64.Off = FilePath;
+ } else if (BaseName.starts_with(ABIVersionPrefix)) {
+ unsigned ABIVersionNumber;
+ if (BaseName.drop_front(ABIVersionPrefix.size())
+ .getAsInteger(/*Redex=*/0, ABIVersionNumber))
+ continue;
+ ABIVersionMap[ABIVersionNumber] = FilePath.str();
} else {
// Process all bitcode filenames that look like
// ocl_isa_version_XXX.amdgcn.bc
const StringRef DeviceLibPrefix = "oclc_isa_version_";
- if (!BaseName.startswith(DeviceLibPrefix))
+ if (!BaseName.starts_with(DeviceLibPrefix))
continue;
StringRef IsaVersionNumber =
@@ -190,9 +199,10 @@ RocmInstallationDetector::getInstallationPathCandidates() {
ROCmSearchDirs.emplace_back(RocmPathArg.str());
DoPrintROCmSearchDirs();
return ROCmSearchDirs;
- } else if (const char *RocmPathEnv = ::getenv("ROCM_PATH")) {
- if (!StringRef(RocmPathEnv).empty()) {
- ROCmSearchDirs.emplace_back(RocmPathEnv);
+ } else if (std::optional<std::string> RocmPathEnv =
+ llvm::sys::Process::GetEnv("ROCM_PATH")) {
+ if (!RocmPathEnv->empty()) {
+ ROCmSearchDirs.emplace_back(std::move(*RocmPathEnv));
DoPrintROCmSearchDirs();
return ROCmSearchDirs;
}
@@ -220,7 +230,7 @@ RocmInstallationDetector::getInstallationPathCandidates() {
// <rocm_root>/llvm-amdgpu-<rocm_release_string>-<hash>/bin directory.
// We only consider the parent directory of llvm-amdgpu package as ROCm
// installation candidate for SPACK.
- if (ParentName.startswith("llvm-amdgpu-")) {
+ if (ParentName.starts_with("llvm-amdgpu-")) {
auto SPACKPostfix =
ParentName.drop_front(strlen("llvm-amdgpu-")).split('-');
auto SPACKReleaseStr = SPACKPostfix.first;
@@ -233,7 +243,7 @@ RocmInstallationDetector::getInstallationPathCandidates() {
// Some versions of the rocm llvm package install to /opt/rocm/llvm/bin
// Some versions of the aomp package install to /opt/rocm/aomp/bin
- if (ParentName == "llvm" || ParentName.startswith("aomp"))
+ if (ParentName == "llvm" || ParentName.starts_with("aomp"))
ParentDir = llvm::sys::path::parent_path(ParentDir);
return Candidate(ParentDir.str(), /*StrictChecking=*/true);
@@ -282,7 +292,7 @@ RocmInstallationDetector::getInstallationPathCandidates() {
FileEnd;
File != FileEnd && !EC; File.increment(EC)) {
llvm::StringRef FileName = llvm::sys::path::filename(File->path());
- if (!FileName.startswith("rocm-"))
+ if (!FileName.starts_with("rocm-"))
continue;
if (LatestROCm.empty()) {
LatestROCm = FileName.str();
@@ -299,6 +309,11 @@ RocmInstallationDetector::getInstallationPathCandidates() {
ROCmSearchDirs.emplace_back(D.SysRoot + "/opt/" + LatestROCm,
/*StrictChecking=*/true);
+ ROCmSearchDirs.emplace_back(D.SysRoot + "/usr/local",
+ /*StrictChecking=*/true);
+ ROCmSearchDirs.emplace_back(D.SysRoot + "/usr",
+ /*StrictChecking=*/true);
+
DoPrintROCmSearchDirs();
return ROCmSearchDirs;
}
@@ -314,6 +329,20 @@ RocmInstallationDetector::RocmInstallationDetector(
RocmDeviceLibPathArg =
Args.getAllArgValues(clang::driver::options::OPT_rocm_device_lib_path_EQ);
HIPPathArg = Args.getLastArgValue(clang::driver::options::OPT_hip_path_EQ);
+ HIPStdParPathArg =
+ Args.getLastArgValue(clang::driver::options::OPT_hipstdpar_path_EQ);
+ HasHIPStdParLibrary =
+ !HIPStdParPathArg.empty() && D.getVFS().exists(HIPStdParPathArg +
+ "/hipstdpar_lib.hpp");
+ HIPRocThrustPathArg =
+ Args.getLastArgValue(clang::driver::options::OPT_hipstdpar_thrust_path_EQ);
+ HasRocThrustLibrary = !HIPRocThrustPathArg.empty() &&
+ D.getVFS().exists(HIPRocThrustPathArg + "/thrust");
+ HIPRocPrimPathArg =
+ Args.getLastArgValue(clang::driver::options::OPT_hipstdpar_prim_path_EQ);
+ HasRocPrimLibrary = !HIPRocPrimPathArg.empty() &&
+ D.getVFS().exists(HIPRocPrimPathArg + "/rocprim");
+
if (auto *A = Args.getLastArg(clang::driver::options::OPT_hip_version_EQ)) {
HIPVersionArg = A->getValue();
unsigned Major = ~0U;
@@ -357,8 +386,9 @@ void RocmInstallationDetector::detectDeviceLibrary() {
if (!RocmDeviceLibPathArg.empty())
LibDevicePath = RocmDeviceLibPathArg[RocmDeviceLibPathArg.size() - 1];
- else if (const char *LibPathEnv = ::getenv("HIP_DEVICE_LIB_PATH"))
- LibDevicePath = LibPathEnv;
+ else if (std::optional<std::string> LibPathEnv =
+ llvm::sys::Process::GetEnv("HIP_DEVICE_LIB_PATH"))
+ LibDevicePath = std::move(*LibPathEnv);
auto &FS = D.getVFS();
if (!LibDevicePath.empty()) {
@@ -373,69 +403,57 @@ void RocmInstallationDetector::detectDeviceLibrary() {
return;
}
- // The install path situation in old versions of ROCm is a real mess, and
- // use a different install layout. Multiple copies of the device libraries
- // exist for each frontend project, and differ depending on which build
- // system produced the packages. Standalone OpenCL builds also have a
- // different directory structure from the ROCm OpenCL package.
- auto &ROCmDirs = getInstallationPathCandidates();
- for (const auto &Candidate : ROCmDirs) {
- auto CandidatePath = Candidate.Path;
-
- // Check device library exists at the given path.
- auto CheckDeviceLib = [&](StringRef Path) {
- bool CheckLibDevice = (!NoBuiltinLibs || Candidate.StrictChecking);
- if (CheckLibDevice && !FS.exists(Path))
- return false;
-
- scanLibDevicePath(Path);
+ // Check device library exists at the given path.
+ auto CheckDeviceLib = [&](StringRef Path, bool StrictChecking) {
+ bool CheckLibDevice = (!NoBuiltinLibs || StrictChecking);
+ if (CheckLibDevice && !FS.exists(Path))
+ return false;
- if (!NoBuiltinLibs) {
- // Check that the required non-target libraries are all available.
- if (!allGenericLibsValid())
- return false;
+ scanLibDevicePath(Path);
- // Check that we have found at least one libdevice that we can link in
- // if -nobuiltinlib hasn't been specified.
- if (LibDeviceMap.empty())
- return false;
- }
- return true;
- };
+ if (!NoBuiltinLibs) {
+ // Check that the required non-target libraries are all available.
+ if (!allGenericLibsValid())
+ return false;
- // The possible structures are:
- // - ${ROCM_ROOT}/amdgcn/bitcode/*
- // - ${ROCM_ROOT}/lib/*
- // - ${ROCM_ROOT}/lib/bitcode/*
- // so try to detect these layouts.
- static constexpr std::array<const char *, 2> SubDirsList[] = {
- {"amdgcn", "bitcode"},
- {"lib", ""},
- {"lib", "bitcode"},
- };
+ // Check that we have found at least one libdevice that we can link in
+ // if -nobuiltinlib hasn't been specified.
+ if (LibDeviceMap.empty())
+ return false;
+ }
+ return true;
+ };
- // Make a path by appending sub-directories to InstallPath.
- auto MakePath = [&](const llvm::ArrayRef<const char *> &SubDirs) {
- auto Path = CandidatePath;
- for (auto SubDir : SubDirs)
- llvm::sys::path::append(Path, SubDir);
- return Path;
- };
+ // Find device libraries in <LLVM_DIR>/lib/clang/<ver>/lib/amdgcn/bitcode
+ LibDevicePath = D.ResourceDir;
+ llvm::sys::path::append(LibDevicePath, CLANG_INSTALL_LIBDIR_BASENAME,
+ "amdgcn", "bitcode");
+ HasDeviceLibrary = CheckDeviceLib(LibDevicePath, true);
+ if (HasDeviceLibrary)
+ return;
- for (auto SubDirs : SubDirsList) {
- LibDevicePath = MakePath(SubDirs);
- HasDeviceLibrary = CheckDeviceLib(LibDevicePath);
- if (HasDeviceLibrary)
- return;
- }
+ // Find device libraries in a legacy ROCm directory structure
+ // ${ROCM_ROOT}/amdgcn/bitcode/*
+ auto &ROCmDirs = getInstallationPathCandidates();
+ for (const auto &Candidate : ROCmDirs) {
+ LibDevicePath = Candidate.Path;
+ llvm::sys::path::append(LibDevicePath, "amdgcn", "bitcode");
+ HasDeviceLibrary = CheckDeviceLib(LibDevicePath, Candidate.StrictChecking);
+ if (HasDeviceLibrary)
+ return;
}
}
void RocmInstallationDetector::detectHIPRuntime() {
SmallVector<Candidate, 4> HIPSearchDirs;
if (!HIPPathArg.empty())
- HIPSearchDirs.emplace_back(HIPPathArg.str(), /*StrictChecking=*/true);
- else
+ HIPSearchDirs.emplace_back(HIPPathArg.str());
+ else if (std::optional<std::string> HIPPathEnv =
+ llvm::sys::Process::GetEnv("HIP_PATH")) {
+ if (!HIPPathEnv->empty())
+ HIPSearchDirs.emplace_back(std::move(*HIPPathEnv));
+ }
+ if (HIPSearchDirs.empty())
HIPSearchDirs.append(getInstallationPathCandidates());
auto &FS = D.getVFS();
@@ -454,18 +472,41 @@ void RocmInstallationDetector::detectHIPRuntime() {
llvm::sys::path::append(IncludePath, "include");
LibPath = InstallPath;
llvm::sys::path::append(LibPath, "lib");
-
- llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> VersionFile =
- FS.getBufferForFile(BinPath + "/.hipVersion");
- if (!VersionFile && Candidate.StrictChecking)
- continue;
-
- if (HIPVersionArg.empty() && VersionFile)
- if (parseHIPVersionFile((*VersionFile)->getBuffer()))
+ SharePath = InstallPath;
+ llvm::sys::path::append(SharePath, "share");
+
+ // Get parent of InstallPath and append "share"
+ SmallString<0> ParentSharePath = llvm::sys::path::parent_path(InstallPath);
+ llvm::sys::path::append(ParentSharePath, "share");
+
+ auto Append = [](SmallString<0> &path, const Twine &a, const Twine &b = "",
+ const Twine &c = "", const Twine &d = "") {
+ SmallString<0> newpath = path;
+ llvm::sys::path::append(newpath, a, b, c, d);
+ return newpath;
+ };
+ // If HIP version file can be found and parsed, use HIP version from there.
+ for (const auto &VersionFilePath :
+ {Append(SharePath, "hip", "version"),
+ Append(ParentSharePath, "hip", "version"),
+ Append(BinPath, ".hipVersion")}) {
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> VersionFile =
+ FS.getBufferForFile(VersionFilePath);
+ if (!VersionFile)
continue;
+ if (HIPVersionArg.empty() && VersionFile)
+ if (parseHIPVersionFile((*VersionFile)->getBuffer()))
+ continue;
- HasHIPRuntime = true;
- return;
+ HasHIPRuntime = true;
+ return;
+ }
+ // Otherwise, if -rocm-path is specified (no strict checking), use the
+ // default HIP version or specified by --hip-version.
+ if (!Candidate.StrictChecking) {
+ HasHIPRuntime = true;
+ return;
+ }
}
HasHIPRuntime = false;
}
@@ -478,7 +519,9 @@ void RocmInstallationDetector::print(raw_ostream &OS) const {
void RocmInstallationDetector::AddHIPIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
- bool UsesRuntimeWrapper = VersionMajorMinor > llvm::VersionTuple(3, 5);
+ bool UsesRuntimeWrapper = VersionMajorMinor > llvm::VersionTuple(3, 5) &&
+ !DriverArgs.hasArg(options::OPT_nohipwrapperinc);
+ bool HasHipStdPar = DriverArgs.hasArg(options::OPT_hipstdpar);
if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
// HIP header includes standard library wrapper headers under clang
@@ -501,18 +544,66 @@ void RocmInstallationDetector::AddHIPIncludeArgs(const ArgList &DriverArgs,
CC1Args.push_back(DriverArgs.MakeArgString(P));
}
- if (DriverArgs.hasArg(options::OPT_nogpuinc))
+ const auto HandleHipStdPar = [=, &DriverArgs, &CC1Args]() {
+ StringRef Inc = getIncludePath();
+ auto &FS = D.getVFS();
+
+ if (!hasHIPStdParLibrary())
+ if (!HIPStdParPathArg.empty() ||
+ !FS.exists(Inc + "/thrust/system/hip/hipstdpar/hipstdpar_lib.hpp")) {
+ D.Diag(diag::err_drv_no_hipstdpar_lib);
+ return;
+ }
+ if (!HasRocThrustLibrary && !FS.exists(Inc + "/thrust")) {
+ D.Diag(diag::err_drv_no_hipstdpar_thrust_lib);
+ return;
+ }
+ if (!HasRocPrimLibrary && !FS.exists(Inc + "/rocprim")) {
+ D.Diag(diag::err_drv_no_hipstdpar_prim_lib);
+ return;
+ }
+ const char *ThrustPath;
+ if (HasRocThrustLibrary)
+ ThrustPath = DriverArgs.MakeArgString(HIPRocThrustPathArg);
+ else
+ ThrustPath = DriverArgs.MakeArgString(Inc + "/thrust");
+
+ const char *HIPStdParPath;
+ if (hasHIPStdParLibrary())
+ HIPStdParPath = DriverArgs.MakeArgString(HIPStdParPathArg);
+ else
+ HIPStdParPath = DriverArgs.MakeArgString(StringRef(ThrustPath) +
+ "/system/hip/hipstdpar");
+
+ const char *PrimPath;
+ if (HasRocPrimLibrary)
+ PrimPath = DriverArgs.MakeArgString(HIPRocPrimPathArg);
+ else
+ PrimPath = DriverArgs.MakeArgString(getIncludePath() + "/rocprim");
+
+ CC1Args.append({"-idirafter", ThrustPath, "-idirafter", PrimPath,
+ "-idirafter", HIPStdParPath, "-include",
+ "hipstdpar_lib.hpp"});
+ };
+
+ if (DriverArgs.hasArg(options::OPT_nogpuinc)) {
+ if (HasHipStdPar)
+ HandleHipStdPar();
+
return;
+ }
if (!hasHIPRuntime()) {
D.Diag(diag::err_drv_no_hip_runtime);
return;
}
- CC1Args.push_back("-internal-isystem");
+ CC1Args.push_back("-idirafter");
CC1Args.push_back(DriverArgs.MakeArgString(getIncludePath()));
if (UsesRuntimeWrapper)
CC1Args.append({"-include", "__clang_hip_runtime_wrapper.h"});
+ if (HasHipStdPar)
+ HandleHipStdPar();
}
void amdgpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -523,9 +614,18 @@ void amdgpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
std::string Linker = getToolChain().GetProgramPath(getShortName());
ArgStringList CmdArgs;
+ CmdArgs.push_back("--no-undefined");
+ CmdArgs.push_back("-shared");
+
addLinkerCompressDebugSectionsOption(getToolChain(), Args, CmdArgs);
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
- CmdArgs.push_back("-shared");
+ if (C.getDriver().isUsingLTO())
+ addLTOOptions(getToolChain(), Args, CmdArgs, Output, Inputs[0],
+ C.getDriver().getLTOMode() == LTOK_Thin);
+ else if (Args.hasArg(options::OPT_mcpu_EQ))
+ CmdArgs.push_back(Args.MakeArgString(
+ "-plugin-opt=mcpu=" + Args.getLastArgValue(options::OPT_mcpu_EQ)));
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
C.addCommand(std::make_unique<Command>(
@@ -544,7 +644,7 @@ void amdgpu::getAMDGPUTargetFeatures(const Driver &D,
llvm::StringMap<bool> FeatureMap;
auto OptionalGpuArch = parseTargetID(Triple, TargetID, &FeatureMap);
if (OptionalGpuArch) {
- StringRef GpuArch = OptionalGpuArch.getValue();
+ StringRef GpuArch = *OptionalGpuArch;
// Iterate through all possible target ID features for the given GPU.
// If it is mapped to true, add +feature.
// If it is mapped to false, add -feature.
@@ -563,8 +663,8 @@ void amdgpu::getAMDGPUTargetFeatures(const Driver &D,
options::OPT_mno_wavefrontsize64, false))
Features.push_back("+wavefrontsize64");
- handleTargetFeaturesGroup(
- Args, Features, options::OPT_m_amdgpu_Features_Group);
+ handleTargetFeaturesGroup(D, Triple, Args, Features,
+ options::OPT_m_amdgpu_Features_Group);
}
/// AMDGPU Toolchain
@@ -596,9 +696,28 @@ AMDGPUToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
if (!DAL)
DAL = new DerivedArgList(Args.getBaseArgs());
- for (Arg *A : Args) {
- if (!shouldSkipArgument(A))
- DAL->append(A);
+ for (Arg *A : Args)
+ DAL->append(A);
+
+ // Replace -mcpu=native with detected GPU.
+ Arg *LastMCPUArg = DAL->getLastArg(options::OPT_mcpu_EQ);
+ if (LastMCPUArg && StringRef(LastMCPUArg->getValue()) == "native") {
+ DAL->eraseArg(options::OPT_mcpu_EQ);
+ auto GPUsOrErr = getSystemGPUArchs(Args);
+ if (!GPUsOrErr) {
+ getDriver().Diag(diag::err_drv_undetermined_gpu_arch)
+ << llvm::Triple::getArchTypeName(getArch())
+ << llvm::toString(GPUsOrErr.takeError()) << "-mcpu";
+ } else {
+ auto &GPUs = *GPUsOrErr;
+ if (GPUs.size() > 1) {
+ getDriver().Diag(diag::warn_drv_multi_gpu_arch)
+ << llvm::Triple::getArchTypeName(getArch())
+ << llvm::join(GPUs, ", ") << "-mcpu";
+ }
+ DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_mcpu_EQ),
+ Args.MakeArgString(GPUs.front()));
+ }
}
checkTargetID(*DAL);
@@ -688,7 +807,7 @@ bool AMDGPUToolChain::isWave64(const llvm::opt::ArgList &DriverArgs,
ROCMToolChain::ROCMToolChain(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: AMDGPUToolChain(D, Triple, Args) {
- RocmInstallation.detectDeviceLibrary();
+ RocmInstallation->detectDeviceLibrary();
}
void AMDGPUToolChain::addClangTargetOptions(
@@ -699,8 +818,7 @@ void AMDGPUToolChain::addClangTargetOptions(
// supported for the foreseeable future.
if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
options::OPT_fvisibility_ms_compat)) {
- CC1Args.push_back("-fvisibility");
- CC1Args.push_back("hidden");
+ CC1Args.push_back("-fvisibility=hidden");
CC1Args.push_back("-fapply-global-visibility-to-externs");
}
}
@@ -715,14 +833,14 @@ AMDGPUToolChain::ParsedTargetIDType
AMDGPUToolChain::getParsedTargetID(const llvm::opt::ArgList &DriverArgs) const {
StringRef TargetID = DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
if (TargetID.empty())
- return {None, None, None};
+ return {std::nullopt, std::nullopt, std::nullopt};
llvm::StringMap<bool> FeatureMap;
auto OptionalGpuArch = parseTargetID(getTriple(), TargetID, &FeatureMap);
if (!OptionalGpuArch)
- return {TargetID.str(), None, None};
+ return {TargetID.str(), std::nullopt, std::nullopt};
- return {TargetID.str(), OptionalGpuArch.getValue().str(), FeatureMap};
+ return {TargetID.str(), OptionalGpuArch->str(), FeatureMap};
}
void AMDGPUToolChain::checkTargetID(
@@ -730,80 +848,33 @@ void AMDGPUToolChain::checkTargetID(
auto PTID = getParsedTargetID(DriverArgs);
if (PTID.OptionalTargetID && !PTID.OptionalGPUArch) {
getDriver().Diag(clang::diag::err_drv_bad_target_id)
- << PTID.OptionalTargetID.getValue();
+ << *PTID.OptionalTargetID;
}
}
-llvm::Error
-AMDGPUToolChain::detectSystemGPUs(const ArgList &Args,
- SmallVector<std::string, 1> &GPUArchs) const {
+Expected<SmallVector<std::string>>
+AMDGPUToolChain::getSystemGPUArchs(const ArgList &Args) const {
+ // Detect AMD GPUs availible on the system.
std::string Program;
if (Arg *A = Args.getLastArg(options::OPT_amdgpu_arch_tool_EQ))
Program = A->getValue();
else
- Program = GetProgramPath(AMDGPU_ARCH_PROGRAM_NAME);
- llvm::SmallString<64> OutputFile;
- llvm::sys::fs::createTemporaryFile("print-system-gpus", "" /* No Suffix */,
- OutputFile);
- llvm::FileRemover OutputRemover(OutputFile.c_str());
- llvm::Optional<llvm::StringRef> Redirects[] = {
- {""},
- OutputFile.str(),
- {""},
- };
-
- std::string ErrorMessage;
- if (int Result = llvm::sys::ExecuteAndWait(
- Program.c_str(), {}, {}, Redirects, /* SecondsToWait */ 0,
- /*MemoryLimit*/ 0, &ErrorMessage)) {
- if (Result > 0) {
- ErrorMessage = "Exited with error code " + std::to_string(Result);
- } else if (Result == -1) {
- ErrorMessage = "Execute failed: " + ErrorMessage;
- } else {
- ErrorMessage = "Crashed: " + ErrorMessage;
- }
+ Program = GetProgramPath("amdgpu-arch");
- return llvm::createStringError(std::error_code(),
- Program + ": " + ErrorMessage);
- }
-
- llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> OutputBuf =
- llvm::MemoryBuffer::getFile(OutputFile.c_str());
- if (!OutputBuf) {
- return llvm::createStringError(OutputBuf.getError(),
- "Failed to read stdout of " + Program +
- ": " + OutputBuf.getError().message());
- }
-
- for (llvm::line_iterator LineIt(**OutputBuf); !LineIt.is_at_end(); ++LineIt) {
- GPUArchs.push_back(LineIt->str());
- }
- return llvm::Error::success();
-}
+ auto StdoutOrErr = executeToolChainProgram(Program);
+ if (!StdoutOrErr)
+ return StdoutOrErr.takeError();
-llvm::Error AMDGPUToolChain::getSystemGPUArch(const ArgList &Args,
- std::string &GPUArch) const {
- // detect the AMDGPU installed in system
SmallVector<std::string, 1> GPUArchs;
- auto Err = detectSystemGPUs(Args, GPUArchs);
- if (Err) {
- return Err;
- }
- if (GPUArchs.empty()) {
+ for (StringRef Arch : llvm::split((*StdoutOrErr)->getBuffer(), "\n"))
+ if (!Arch.empty())
+ GPUArchs.push_back(Arch.str());
+
+ if (GPUArchs.empty())
return llvm::createStringError(std::error_code(),
"No AMD GPU detected in the system");
- }
- GPUArch = GPUArchs[0];
- if (GPUArchs.size() > 1) {
- bool AllSame = std::all_of(
- GPUArchs.begin(), GPUArchs.end(),
- [&](const StringRef &GPUArch) { return GPUArch == GPUArchs.front(); });
- if (!AllSame)
- return llvm::createStringError(
- std::error_code(), "Multiple AMD GPUs found with different archs");
- }
- return llvm::Error::success();
+
+ return std::move(GPUArchs);
}
void ROCMToolChain::addClangTargetOptions(
@@ -821,20 +892,16 @@ void ROCMToolChain::addClangTargetOptions(
if (DriverArgs.hasArg(options::OPT_nogpulib))
return;
- if (!RocmInstallation.hasDeviceLibrary()) {
- getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 0;
- return;
- }
-
// Get the device name and canonicalize it
const StringRef GpuArch = getGPUArch(DriverArgs);
auto Kind = llvm::AMDGPU::parseArchAMDGCN(GpuArch);
const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind);
- std::string LibDeviceFile = RocmInstallation.getLibDeviceFile(CanonArch);
- if (LibDeviceFile.empty()) {
- getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 1 << GpuArch;
+ StringRef LibDeviceFile = RocmInstallation->getLibDeviceFile(CanonArch);
+ auto ABIVer = DeviceLibABIVersion::fromCodeObjectVersion(
+ getAMDGPUCodeObjectVersion(getDriver(), DriverArgs));
+ if (!RocmInstallation->checkCommonBitcodeLibs(CanonArch, LibDeviceFile,
+ ABIVer))
return;
- }
bool Wave64 = isWave64(DriverArgs, Kind);
@@ -852,59 +919,75 @@ void ROCMToolChain::addClangTargetOptions(
// Add the OpenCL specific bitcode library.
llvm::SmallVector<std::string, 12> BCLibs;
- BCLibs.push_back(RocmInstallation.getOpenCLPath().str());
+ BCLibs.push_back(RocmInstallation->getOpenCLPath().str());
// Add the generic set of libraries.
- BCLibs.append(RocmInstallation.getCommonBitcodeLibs(
+ BCLibs.append(RocmInstallation->getCommonBitcodeLibs(
DriverArgs, LibDeviceFile, Wave64, DAZ, FiniteOnly, UnsafeMathOpt,
- FastRelaxedMath, CorrectSqrt));
+ FastRelaxedMath, CorrectSqrt, ABIVer, false));
- llvm::for_each(BCLibs, [&](StringRef BCFile) {
+ for (StringRef BCFile : BCLibs) {
CC1Args.push_back("-mlink-builtin-bitcode");
CC1Args.push_back(DriverArgs.MakeArgString(BCFile));
- });
+ }
+}
+
+bool RocmInstallationDetector::checkCommonBitcodeLibs(
+ StringRef GPUArch, StringRef LibDeviceFile,
+ DeviceLibABIVersion ABIVer) const {
+ if (!hasDeviceLibrary()) {
+ D.Diag(diag::err_drv_no_rocm_device_lib) << 0;
+ return false;
+ }
+ if (LibDeviceFile.empty()) {
+ D.Diag(diag::err_drv_no_rocm_device_lib) << 1 << GPUArch;
+ return false;
+ }
+ if (ABIVer.requiresLibrary() && getABIVersionPath(ABIVer).empty()) {
+ D.Diag(diag::err_drv_no_rocm_device_lib) << 2 << ABIVer.toString();
+ return false;
+ }
+ return true;
}
llvm::SmallVector<std::string, 12>
RocmInstallationDetector::getCommonBitcodeLibs(
const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile, bool Wave64,
bool DAZ, bool FiniteOnly, bool UnsafeMathOpt, bool FastRelaxedMath,
- bool CorrectSqrt) const {
-
+ bool CorrectSqrt, DeviceLibABIVersion ABIVer, bool isOpenMP = false) const {
llvm::SmallVector<std::string, 12> BCLibs;
auto AddBCLib = [&](StringRef BCFile) { BCLibs.push_back(BCFile.str()); };
AddBCLib(getOCMLPath());
- AddBCLib(getOCKLPath());
+ if (!isOpenMP)
+ AddBCLib(getOCKLPath());
AddBCLib(getDenormalsAreZeroPath(DAZ));
AddBCLib(getUnsafeMathPath(UnsafeMathOpt || FastRelaxedMath));
AddBCLib(getFiniteOnlyPath(FiniteOnly || FastRelaxedMath));
AddBCLib(getCorrectlyRoundedSqrtPath(CorrectSqrt));
AddBCLib(getWavefrontSize64Path(Wave64));
AddBCLib(LibDeviceFile);
+ auto ABIVerPath = getABIVersionPath(ABIVer);
+ if (!ABIVerPath.empty())
+ AddBCLib(ABIVerPath);
return BCLibs;
}
-bool AMDGPUToolChain::shouldSkipArgument(const llvm::opt::Arg *A) const {
- Option O = A->getOption();
- if (O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie))
- return true;
- return false;
-}
-
llvm::SmallVector<std::string, 12>
ROCMToolChain::getCommonDeviceLibNames(const llvm::opt::ArgList &DriverArgs,
- const std::string &GPUArch) const {
+ const std::string &GPUArch,
+ bool isOpenMP) const {
auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch);
const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind);
- std::string LibDeviceFile = RocmInstallation.getLibDeviceFile(CanonArch);
- if (LibDeviceFile.empty()) {
- getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 1 << GPUArch;
+ StringRef LibDeviceFile = RocmInstallation->getLibDeviceFile(CanonArch);
+ auto ABIVer = DeviceLibABIVersion::fromCodeObjectVersion(
+ getAMDGPUCodeObjectVersion(getDriver(), DriverArgs));
+ if (!RocmInstallation->checkCommonBitcodeLibs(CanonArch, LibDeviceFile,
+ ABIVer))
return {};
- }
// If --hip-device-lib is not set, add the default bitcode libraries.
// TODO: There are way too many flags that change this. Do we need to check
@@ -921,10 +1004,10 @@ ROCMToolChain::getCommonDeviceLibNames(const llvm::opt::ArgList &DriverArgs,
options::OPT_fno_fast_math, false);
bool CorrectSqrt = DriverArgs.hasFlag(
options::OPT_fhip_fp32_correctly_rounded_divide_sqrt,
- options::OPT_fno_hip_fp32_correctly_rounded_divide_sqrt);
+ options::OPT_fno_hip_fp32_correctly_rounded_divide_sqrt, true);
bool Wave64 = isWave64(DriverArgs, Kind);
- return RocmInstallation.getCommonBitcodeLibs(
+ return RocmInstallation->getCommonBitcodeLibs(
DriverArgs, LibDeviceFile, Wave64, DAZ, FiniteOnly, UnsafeMathOpt,
- FastRelaxedMath, CorrectSqrt);
-} \ No newline at end of file
+ FastRelaxedMath, CorrectSqrt, ABIVer, isOpenMP);
+}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/AMDGPU.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/AMDGPU.h
index a4bcf315ca76..b3361b1e3607 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/AMDGPU.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/AMDGPU.h
@@ -16,7 +16,7 @@
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/TargetParser.h"
+#include "llvm/TargetParser/TargetParser.h"
#include <map>
@@ -26,7 +26,7 @@ namespace driver {
namespace tools {
namespace amdgpu {
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
public:
Linker(const ToolChain &TC) : Tool("amdgpu::Linker", "ld.lld", TC) {}
bool isLinkJob() const override { return true; }
@@ -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,15 +60,15 @@ protected:
public:
AMDGPUToolChain(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
- unsigned GetDefaultDwarfVersion() const override { return 4; }
- bool IsIntegratedAssemblerDefault() const override { return true; }
- bool IsMathErrnoDefault() const override { return false; }
+ unsigned GetDefaultDwarfVersion() const override { return 5; }
- bool useIntegratedAs() const override { return true; }
+ bool IsMathErrnoDefault() const override { return false; }
bool isCrossCompiling() const override { return true; }
- bool isPICDefault() const override { return false; }
- bool isPIEDefault() const override { return false; }
- bool isPICDefaultForced() const override { return false; }
+ bool isPICDefault() const override { return true; }
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override {
+ return false;
+ }
+ bool isPICDefaultForced() const override { return true; }
bool SupportsProfiling() const override { return false; }
llvm::opt::DerivedArgList *
@@ -97,13 +97,10 @@ public:
/// Needed for translating LTO options.
const char *getDefaultLinker() const override { return "ld.lld"; }
- /// Should skip argument.
- bool shouldSkipArgument(const llvm::opt::Arg *Arg) const;
-
- /// Uses amdgpu_arch tool to get arch of the system GPU. Will return error
+ /// Uses amdgpu-arch tool to get arch of the system GPU. Will return error
/// if unable to find one.
- llvm::Error getSystemGPUArch(const llvm::opt::ArgList &Args,
- std::string &GPUArch) const;
+ virtual Expected<SmallVector<std::string>>
+ getSystemGPUArchs(const llvm::opt::ArgList &Args) const override;
protected:
/// Check and diagnose invalid target ID specified by -mcpu.
@@ -111,9 +108,9 @@ protected:
/// The struct type returned by getParsedTargetID.
struct ParsedTargetIDType {
- Optional<std::string> OptionalTargetID;
- Optional<std::string> OptionalGPUArch;
- Optional<llvm::StringMap<bool>> OptionalFeatures;
+ std::optional<std::string> OptionalTargetID;
+ std::optional<std::string> OptionalGPUArch;
+ std::optional<llvm::StringMap<bool>> OptionalFeatures;
};
/// Get target ID, GPU arch, and target ID features if the target ID is
@@ -124,8 +121,6 @@ protected:
/// Get GPU arch from -mcpu without checking.
StringRef getGPUArch(const llvm::opt::ArgList &DriverArgs) const;
- llvm::Error detectSystemGPUs(const llvm::opt::ArgList &Args,
- SmallVector<std::string, 1> &GPUArchs) const;
};
class LLVM_LIBRARY_VISIBILITY ROCMToolChain : public AMDGPUToolChain {
@@ -140,7 +135,8 @@ public:
// Returns a list of device library names shared by different languages
llvm::SmallVector<std::string, 12>
getCommonDeviceLibNames(const llvm::opt::ArgList &DriverArgs,
- const std::string &GPUArch) const;
+ const std::string &GPUArch,
+ bool isOpenMP = false) const;
};
} // end namespace toolchains
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
index 135e3694434d..b012b7cb7293 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
@@ -16,6 +16,7 @@
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Options.h"
+#include "clang/Driver/Tool.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatAdapters.h"
@@ -28,199 +29,13 @@ using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;
-namespace {
-
-static const char *getOutputFileName(Compilation &C, StringRef Base,
- const char *Postfix,
- const char *Extension) {
- const char *OutputFileName;
- if (C.getDriver().isSaveTempsEnabled()) {
- OutputFileName =
- C.getArgs().MakeArgString(Base.str() + Postfix + "." + Extension);
- } else {
- std::string TmpName =
- C.getDriver().GetTemporaryPath(Base.str() + Postfix, Extension);
- OutputFileName = C.addTempFile(C.getArgs().MakeArgString(TmpName));
- }
- return OutputFileName;
-}
-
-static void addLLCOptArg(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) {
- if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
- StringRef OOpt = "0";
- if (A->getOption().matches(options::OPT_O4) ||
- A->getOption().matches(options::OPT_Ofast))
- OOpt = "3";
- else if (A->getOption().matches(options::OPT_O0))
- OOpt = "0";
- else if (A->getOption().matches(options::OPT_O)) {
- // Clang and opt support -Os/-Oz; llc only supports -O0, -O1, -O2 and -O3
- // so we map -Os/-Oz to -O2.
- // Only clang supports -Og, and maps it to -O1.
- // We map anything else to -O2.
- OOpt = llvm::StringSwitch<const char *>(A->getValue())
- .Case("1", "1")
- .Case("2", "2")
- .Case("3", "3")
- .Case("s", "2")
- .Case("z", "2")
- .Case("g", "1")
- .Default("0");
- }
- CmdArgs.push_back(Args.MakeArgString("-O" + OOpt));
- }
-}
-
-static bool checkSystemForAMDGPU(const ArgList &Args, const AMDGPUToolChain &TC,
- std::string &GPUArch) {
- if (auto Err = TC.getSystemGPUArch(Args, GPUArch)) {
- std::string ErrMsg =
- llvm::formatv("{0}", llvm::fmt_consume(std::move(Err)));
- TC.getDriver().Diag(diag::err_drv_undetermined_amdgpu_arch) << ErrMsg;
- return false;
- }
-
- return true;
-}
-} // namespace
-
-const char *AMDGCN::OpenMPLinker::constructLLVMLinkCommand(
- 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) {
- SmallVector<std::string, 12> BCLibs =
- AMDGPUOpenMPTC.getCommonDeviceLibNames(Args, SubArchName.str());
- llvm::for_each(BCLibs, [&](StringRef BCFile) {
- CmdArgs.push_back(Args.MakeArgString(BCFile));
- });
- }
- }
-
- // Add an intermediate output file.
- CmdArgs.push_back("-o");
- const char *OutputFileName =
- getOutputFileName(C, OutputFilePrefix, "-linked", "bc");
- CmdArgs.push_back(OutputFileName);
- const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("llvm-link"));
- C.addCommand(std::make_unique<Command>(
- JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs,
- InputInfo(&JA, Args.MakeArgString(OutputFileName))));
- return OutputFileName;
-}
-
-const char *AMDGCN::OpenMPLinker::constructLlcCommand(
- Compilation &C, const JobAction &JA, const InputInfoList &Inputs,
- const llvm::opt::ArgList &Args, llvm::StringRef SubArchName,
- llvm::StringRef OutputFilePrefix, const char *InputFileName,
- bool OutputIsAsm) const {
- // Construct llc command.
- ArgStringList LlcArgs;
- // The input to llc is the output from opt.
- LlcArgs.push_back(InputFileName);
- // Pass optimization arg to llc.
- addLLCOptArg(Args, LlcArgs);
- LlcArgs.push_back("-mtriple=amdgcn-amd-amdhsa");
- LlcArgs.push_back(Args.MakeArgString("-mcpu=" + SubArchName));
- LlcArgs.push_back(
- Args.MakeArgString(Twine("-filetype=") + (OutputIsAsm ? "asm" : "obj")));
-
- for (const Arg *A : Args.filtered(options::OPT_mllvm)) {
- LlcArgs.push_back(A->getValue(0));
- }
-
- // Add output filename
- LlcArgs.push_back("-o");
- const char *LlcOutputFile =
- getOutputFileName(C, OutputFilePrefix, "", OutputIsAsm ? "s" : "o");
- LlcArgs.push_back(LlcOutputFile);
- const char *Llc = Args.MakeArgString(getToolChain().GetProgramPath("llc"));
- C.addCommand(std::make_unique<Command>(
- JA, *this, ResponseFileSupport::AtFileCurCP(), Llc, LlcArgs, Inputs,
- InputInfo(&JA, Args.MakeArgString(LlcOutputFile))));
- return LlcOutputFile;
-}
-
-void AMDGCN::OpenMPLinker::constructLldCommand(
- Compilation &C, const JobAction &JA, const InputInfoList &Inputs,
- const InputInfo &Output, const llvm::opt::ArgList &Args,
- const char *InputFileName) const {
- // Construct lld command.
- // The output from ld.lld is an HSA code object file.
- ArgStringList LldArgs{"-flavor", "gnu", "--no-undefined",
- "-shared", "-o", Output.getFilename(),
- InputFileName};
-
- const char *Lld = Args.MakeArgString(getToolChain().GetProgramPath("lld"));
- C.addCommand(std::make_unique<Command>(
- JA, *this, ResponseFileSupport::AtFileCurCP(), Lld, LldArgs, Inputs,
- InputInfo(&JA, Args.MakeArgString(Output.getFilename()))));
-}
-
-// For amdgcn the inputs of the linker job are device bitcode and output is
-// object file. It calls llvm-link, opt, llc, then lld steps.
-void AMDGCN::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
- const ToolChain &TC = getToolChain();
- assert(getToolChain().getTriple().isAMDGCN() && "Unsupported target");
-
- const toolchains::AMDGPUOpenMPToolChain &AMDGPUOpenMPTC =
- static_cast<const toolchains::AMDGPUOpenMPToolChain &>(TC);
-
- std::string GPUArch = Args.getLastArgValue(options::OPT_march_EQ).str();
- if (GPUArch.empty()) {
- if (!checkSystemForAMDGPU(Args, AMDGPUOpenMPTC, GPUArch))
- return;
- }
-
- // Prefix for temporary file name.
- std::string Prefix;
- for (const auto &II : Inputs)
- if (II.isFilename())
- Prefix = llvm::sys::path::stem(II.getFilename()).str() + "-" + GPUArch;
- assert(Prefix.length() && "no linker inputs are files ");
-
- // Each command outputs different files.
- const char *LLVMLinkCommand = constructLLVMLinkCommand(
- AMDGPUOpenMPTC, C, JA, Inputs, Args, GPUArch, Prefix);
-
- // Produce readable assembly if save-temps is enabled.
- if (C.getDriver().isSaveTempsEnabled())
- constructLlcCommand(C, JA, Inputs, Args, GPUArch, Prefix, LLVMLinkCommand,
- /*OutputIsAsm=*/true);
- const char *LlcCommand = constructLlcCommand(C, JA, Inputs, Args, GPUArch,
- Prefix, LLVMLinkCommand);
- constructLldCommand(C, JA, Inputs, Output, Args, LlcCommand);
-}
-
AMDGPUOpenMPToolChain::AMDGPUOpenMPToolChain(const Driver &D,
const llvm::Triple &Triple,
const ToolChain &HostTC,
const ArgList &Args)
: ROCMToolChain(D, Triple, Args), HostTC(HostTC) {
// Lookup binaries into the driver directory, this is used to
- // discover the clang-offload-bundler executable.
+ // discover the 'amdgpu-arch' executable.
getProgramPaths().push_back(getDriver().Dir);
}
@@ -229,11 +44,8 @@ void AMDGPUOpenMPToolChain::addClangTargetOptions(
Action::OffloadKind DeviceOffloadingKind) const {
HostTC.addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadingKind);
- std::string GPUArch = DriverArgs.getLastArgValue(options::OPT_march_EQ).str();
- if (GPUArch.empty()) {
- if (!checkSystemForAMDGPU(DriverArgs, *this, GPUArch))
- return;
- }
+ StringRef GPUArch = DriverArgs.getLastArgValue(options::OPT_march_EQ);
+ assert(!GPUArch.empty() && "Must have an explicit GPU arch.");
assert(DeviceOffloadingKind == Action::OFK_OpenMP &&
"Only OpenMP offloading kinds are supported.");
@@ -245,15 +57,15 @@ void AMDGPUOpenMPToolChain::addClangTargetOptions(
if (DriverArgs.hasArg(options::OPT_nogpulib))
return;
- std::string BitcodeSuffix;
- if (DriverArgs.hasFlag(options::OPT_fopenmp_target_new_runtime,
- options::OPT_fno_openmp_target_new_runtime, false))
- BitcodeSuffix = "new-amdgcn-" + GPUArch;
- else
- BitcodeSuffix = "amdgcn-" + GPUArch;
+ for (auto BCFile : getDeviceLibs(DriverArgs)) {
+ CC1Args.push_back(BCFile.ShouldInternalize ? "-mlink-builtin-bitcode"
+ : "-mlink-bitcode-file");
+ CC1Args.push_back(DriverArgs.MakeArgString(BCFile.Path));
+ }
- addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, BitcodeSuffix,
- getTriple());
+ // Link the bitcode library late if we're using device LTO.
+ if (getDriver().isUsingLTO(/* IsOffload */ true))
+ return;
}
llvm::opt::DerivedArgList *AMDGPUOpenMPToolChain::TranslateArgs(
@@ -266,10 +78,33 @@ llvm::opt::DerivedArgList *AMDGPUOpenMPToolChain::TranslateArgs(
const OptTable &Opts = getDriver().getOpts();
- if (DeviceOffloadKind != Action::OFK_OpenMP) {
- for (Arg *A : Args) {
- DAL->append(A);
+ if (DeviceOffloadKind == Action::OFK_OpenMP) {
+ for (Arg *A : Args)
+ if (!llvm::is_contained(*DAL, A))
+ DAL->append(A);
+
+ if (!DAL->hasArg(options::OPT_march_EQ)) {
+ StringRef Arch = BoundArch;
+ if (Arch.empty()) {
+ auto ArchsOrErr = getSystemGPUArchs(Args);
+ if (!ArchsOrErr) {
+ std::string ErrMsg =
+ llvm::formatv("{0}", llvm::fmt_consume(ArchsOrErr.takeError()));
+ getDriver().Diag(diag::err_drv_undetermined_gpu_arch)
+ << llvm::Triple::getArchTypeName(getArch()) << ErrMsg << "-march";
+ Arch = CudaArchToString(CudaArch::HIPDefault);
+ } else {
+ Arch = Args.MakeArgString(ArchsOrErr->front());
+ }
+ }
+ DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), Arch);
}
+
+ return DAL;
+ }
+
+ for (Arg *A : Args) {
+ DAL->append(A);
}
if (!BoundArch.empty()) {
@@ -281,11 +116,6 @@ llvm::opt::DerivedArgList *AMDGPUOpenMPToolChain::TranslateArgs(
return DAL;
}
-Tool *AMDGPUOpenMPToolChain::buildLinker() const {
- assert(getTriple().isAMDGCN());
- return new tools::AMDGCN::OpenMPLinker(*this);
-}
-
void AMDGPUOpenMPToolChain::addClangWarningOptions(
ArgStringList &CC1Args) const {
HostTC.addClangWarningOptions(CC1Args);
@@ -324,3 +154,24 @@ AMDGPUOpenMPToolChain::computeMSVCVersion(const Driver *D,
const ArgList &Args) const {
return HostTC.computeMSVCVersion(D, Args);
}
+
+llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
+AMDGPUOpenMPToolChain::getDeviceLibs(const llvm::opt::ArgList &Args) const {
+ if (Args.hasArg(options::OPT_nogpulib))
+ return {};
+
+ if (!RocmInstallation->hasDeviceLibrary()) {
+ getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 0;
+ return {};
+ }
+
+ StringRef GpuArch = getProcessorFromTargetID(
+ getTriple(), Args.getLastArgValue(options::OPT_march_EQ));
+
+ SmallVector<BitCodeLibraryInfo, 12> BCLibs;
+ for (auto BCLib : getCommonDeviceLibNames(Args, GpuArch.str(),
+ /*IsOpenMP=*/true))
+ BCLibs.emplace_back(BCLib);
+
+ return BCLibs;
+}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h
index 233256bf7378..2be444a42c55 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h
@@ -20,49 +20,6 @@ namespace toolchains {
class AMDGPUOpenMPToolChain;
}
-namespace tools {
-
-namespace AMDGCN {
-// Runs llvm-link/opt/llc/lld, which links multiple LLVM bitcode, together with
-// device library, then compiles it to ISA in a shared object.
-class LLVM_LIBRARY_VISIBILITY OpenMPLinker : public Tool {
-public:
- OpenMPLinker(const ToolChain &TC)
- : Tool("AMDGCN::OpenMPLinker", "amdgcn-link", TC) {}
-
- bool hasIntegratedCPP() const override { return false; }
-
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
-
-private:
- /// \return llvm-link output file name.
- 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,
- const InputInfoList &Inputs,
- const llvm::opt::ArgList &Args,
- llvm::StringRef SubArchName,
- llvm::StringRef OutputFilePrefix,
- const char *InputFileName,
- bool OutputIsAsm = false) const;
-
- void constructLldCommand(Compilation &C, const JobAction &JA,
- const InputInfoList &Inputs, const InputInfo &Output,
- const llvm::opt::ArgList &Args,
- const char *InputFileName) const;
-};
-
-} // end namespace AMDGCN
-} // end namespace tools
-
namespace toolchains {
class LLVM_LIBRARY_VISIBILITY AMDGPUOpenMPToolChain final
@@ -97,10 +54,10 @@ public:
computeMSVCVersion(const Driver *D,
const llvm::opt::ArgList &Args) const override;
- const ToolChain &HostTC;
+ llvm::SmallVector<BitCodeLibraryInfo, 12>
+ getDeviceLibs(const llvm::opt::ArgList &Args) const override;
-protected:
- Tool *buildLinker() const override;
+ const ToolChain &HostTC;
};
} // end namespace toolchains
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/AVR.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/AVR.cpp
index f147292038a8..bb5c0e6db997 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/AVR.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/AVR.cpp
@@ -12,13 +12,12 @@
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Options.h"
-#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringSwitch.h"
#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/TargetParser/SubtargetFeature.h"
using namespace clang::driver;
using namespace clang::driver::toolchains;
@@ -28,9 +27,10 @@ using namespace llvm::opt;
namespace {
-const struct {
+// NOTE: This list has been synchronized with gcc-avr 7.3.0 and avr-libc 2.0.0.
+constexpr struct {
StringRef Name;
- std::string SubPath;
+ StringRef SubPath;
StringRef Family;
unsigned DataAddr;
} MCUInfo[] = {
@@ -62,6 +62,7 @@ const struct {
{"attiny261a", "avr25/tiny-stack", "avr25", 0x800060},
{"at86rf401", "avr25", "avr25", 0x800060},
{"ata5272", "avr25", "avr25", 0x800100},
+ {"ata6616c", "avr25", "avr25", 0x800100},
{"attiny4313", "avr25", "avr25", 0x800060},
{"attiny44", "avr25", "avr25", 0x800060},
{"attiny44a", "avr25", "avr25", 0x800060},
@@ -88,6 +89,8 @@ const struct {
{"at90usb82", "avr35", "avr35", 0x800100},
{"at90usb162", "avr35", "avr35", 0x800100},
{"ata5505", "avr35", "avr35", 0x800100},
+ {"ata6617c", "avr35", "avr35", 0x800100},
+ {"ata664251", "avr35", "avr35", 0x800100},
{"atmega8u2", "avr35", "avr35", 0x800100},
{"atmega16u2", "avr35", "avr35", 0x800100},
{"atmega32u2", "avr35", "avr35", 0x800100},
@@ -97,6 +100,7 @@ const struct {
{"atmega8a", "avr4", "avr4", 0x800060},
{"ata6285", "avr4", "avr4", 0x800100},
{"ata6286", "avr4", "avr4", 0x800100},
+ {"ata6612c", "avr4", "avr4", 0x800100},
{"atmega48", "avr4", "avr4", 0x800100},
{"atmega48a", "avr4", "avr4", 0x800100},
{"atmega48pa", "avr4", "avr4", 0x800100},
@@ -116,8 +120,17 @@ const struct {
{"at90pwm3", "avr4", "avr4", 0x800100},
{"at90pwm3b", "avr4", "avr4", 0x800100},
{"at90pwm81", "avr4", "avr4", 0x800100},
+ {"ata5702m322", "avr5", "avr5", 0x800200},
+ {"ata5782", "avr5", "avr5", 0x800200},
{"ata5790", "avr5", "avr5", 0x800100},
+ {"ata5790n", "avr5", "avr5", 0x800100},
+ {"ata5791", "avr5", "avr5", 0x800100},
{"ata5795", "avr5", "avr5", 0x800100},
+ {"ata5831", "avr5", "avr5", 0x800200},
+ {"ata6613c", "avr5", "avr5", 0x800100},
+ {"ata6614q", "avr5", "avr5", 0x800100},
+ {"ata8210", "avr5", "avr5", 0x800200},
+ {"ata8510", "avr5", "avr5", 0x800200},
{"atmega16", "avr5", "avr5", 0x800060},
{"atmega16a", "avr5", "avr5", 0x800060},
{"atmega161", "avr5", "avr5", 0x800060},
@@ -145,6 +158,7 @@ const struct {
{"atmega324a", "avr5", "avr5", 0x800100},
{"atmega324p", "avr5", "avr5", 0x800100},
{"atmega324pa", "avr5", "avr5", 0x800100},
+ {"atmega324pb", "avr5", "avr5", 0x800100},
{"atmega325", "avr5", "avr5", 0x800100},
{"atmega325a", "avr5", "avr5", 0x800100},
{"atmega325p", "avr5", "avr5", 0x800100},
@@ -155,6 +169,7 @@ const struct {
{"atmega3250pa", "avr5", "avr5", 0x800100},
{"atmega328", "avr5", "avr5", 0x800100},
{"atmega328p", "avr5", "avr5", 0x800100},
+ {"atmega328pb", "avr5", "avr5", 0x800100},
{"atmega329", "avr5", "avr5", 0x800100},
{"atmega329a", "avr5", "avr5", 0x800100},
{"atmega329p", "avr5", "avr5", 0x800100},
@@ -192,6 +207,7 @@ const struct {
{"atmega32hvb", "avr5", "avr5", 0x800100},
{"atmega32hvbrevb", "avr5", "avr5", 0x800100},
{"atmega64hve", "avr5", "avr5", 0x800100},
+ {"atmega64hve2", "avr5", "avr5", 0x800100},
{"at90can32", "avr5", "avr5", 0x800100},
{"at90can64", "avr5", "avr5", 0x800100},
{"at90pwm161", "avr5", "avr5", 0x800100},
@@ -232,17 +248,22 @@ const struct {
{"attiny10", "avrtiny", "avrtiny", 0x800040},
{"attiny20", "avrtiny", "avrtiny", 0x800040},
{"attiny40", "avrtiny", "avrtiny", 0x800040},
+ {"attiny102", "avrtiny", "avrtiny", 0x800040},
+ {"attiny104", "avrtiny", "avrtiny", 0x800040},
{"atxmega16a4", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega16a4u", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega16c4", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega16d4", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega32a4", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega32a4u", "avrxmega2", "avrxmega2", 0x802000},
+ {"atxmega32c3", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega32c4", "avrxmega2", "avrxmega2", 0x802000},
+ {"atxmega32d3", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega32d4", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega32e5", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega16e5", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega8e5", "avrxmega2", "avrxmega2", 0x802000},
+ {"atxmega64a3", "avrxmega4", "avrxmega4", 0x802000},
{"atxmega64a3u", "avrxmega4", "avrxmega4", 0x802000},
{"atxmega64a4u", "avrxmega4", "avrxmega4", 0x802000},
{"atxmega64b1", "avrxmega4", "avrxmega4", 0x802000},
@@ -274,6 +295,42 @@ const struct {
{"atxmega128a1", "avrxmega7", "avrxmega7", 0x802000},
{"atxmega128a1u", "avrxmega7", "avrxmega7", 0x802000},
{"atxmega128a4u", "avrxmega7", "avrxmega7", 0x802000},
+ {"attiny202", "avrxmega3/short-calls", "avrxmega3", 0x803F80},
+ {"attiny204", "avrxmega3/short-calls", "avrxmega3", 0x803F80},
+ {"attiny212", "avrxmega3/short-calls", "avrxmega3", 0x803F80},
+ {"attiny214", "avrxmega3/short-calls", "avrxmega3", 0x803F80},
+ {"attiny402", "avrxmega3/short-calls", "avrxmega3", 0x803F00},
+ {"attiny404", "avrxmega3/short-calls", "avrxmega3", 0x803F00},
+ {"attiny406", "avrxmega3/short-calls", "avrxmega3", 0x803F00},
+ {"attiny412", "avrxmega3/short-calls", "avrxmega3", 0x803F00},
+ {"attiny414", "avrxmega3/short-calls", "avrxmega3", 0x803F00},
+ {"attiny416", "avrxmega3/short-calls", "avrxmega3", 0x803F00},
+ {"attiny417", "avrxmega3/short-calls", "avrxmega3", 0x803F00},
+ {"attiny804", "avrxmega3/short-calls", "avrxmega3", 0x803E00},
+ {"attiny806", "avrxmega3/short-calls", "avrxmega3", 0x803E00},
+ {"attiny807", "avrxmega3/short-calls", "avrxmega3", 0x803E00},
+ {"attiny814", "avrxmega3/short-calls", "avrxmega3", 0x803E00},
+ {"attiny816", "avrxmega3/short-calls", "avrxmega3", 0x803E00},
+ {"attiny817", "avrxmega3/short-calls", "avrxmega3", 0x803E00},
+ {"atmega808", "avrxmega3/short-calls", "avrxmega3", 0x803C00},
+ {"atmega809", "avrxmega3/short-calls", "avrxmega3", 0x803C00},
+ {"atmega1608", "avrxmega3", "avrxmega3", 0x803800},
+ {"atmega1609", "avrxmega3", "avrxmega3", 0x803800},
+ {"atmega3208", "avrxmega3", "avrxmega3", 0x803000},
+ {"atmega3209", "avrxmega3", "avrxmega3", 0x803000},
+ {"atmega4808", "avrxmega3", "avrxmega3", 0x802800},
+ {"atmega4809", "avrxmega3", "avrxmega3", 0x802800},
+ {"attiny1604", "avrxmega3", "avrxmega3", 0x803C00},
+ {"attiny1606", "avrxmega3", "avrxmega3", 0x803C00},
+ {"attiny1607", "avrxmega3", "avrxmega3", 0x803C00},
+ {"attiny1614", "avrxmega3", "avrxmega3", 0x803800},
+ {"attiny1616", "avrxmega3", "avrxmega3", 0x803800},
+ {"attiny1617", "avrxmega3", "avrxmega3", 0x803800},
+ {"attiny1624", "avrxmega3", "avrxmega3", 0x803800},
+ {"attiny1626", "avrxmega3", "avrxmega3", 0x803800},
+ {"attiny1627", "avrxmega3", "avrxmega3", 0x803800},
+ {"attiny3216", "avrxmega3", "avrxmega3", 0x803800},
+ {"attiny3217", "avrxmega3", "avrxmega3", 0x803800},
};
std::string GetMCUSubPath(StringRef MCUName) {
@@ -283,21 +340,22 @@ std::string GetMCUSubPath(StringRef MCUName) {
return "";
}
-llvm::Optional<StringRef> GetMCUFamilyName(StringRef MCUName) {
+std::optional<StringRef> GetMCUFamilyName(StringRef MCUName) {
for (const auto &MCU : MCUInfo)
if (MCU.Name == MCUName)
- return Optional<StringRef>(MCU.Family);
- return Optional<StringRef>();
+ return std::optional<StringRef>(MCU.Family);
+ return std::nullopt;
}
-llvm::Optional<unsigned> GetMCUSectionAddressData(StringRef MCUName) {
+std::optional<unsigned> GetMCUSectionAddressData(StringRef MCUName) {
for (const auto &MCU : MCUInfo)
if (MCU.Name == MCUName && MCU.DataAddr > 0)
- return Optional<unsigned>(MCU.DataAddr);
- return Optional<unsigned>();
+ return std::optional<unsigned>(MCU.DataAddr);
+ return std::nullopt;
}
const StringRef PossibleAVRLibcLocations[] = {
+ "/avr",
"/usr/avr",
"/usr/lib/avr",
};
@@ -307,49 +365,18 @@ const StringRef PossibleAVRLibcLocations[] = {
/// AVR Toolchain
AVRToolChain::AVRToolChain(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
- : Generic_ELF(D, Triple, Args), LinkStdlib(false) {
+ : Generic_ELF(D, Triple, Args) {
GCCInstallation.init(Triple, Args);
+ if (getCPUName(D, Args, Triple).empty())
+ D.Diag(diag::warn_drv_avr_mcu_not_specified);
+
// Only add default libraries if the user hasn't explicitly opted out.
if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nodefaultlibs) &&
- !Args.hasArg(options::OPT_c /* does not apply when not linking */)) {
- std::string CPU = getCPUName(Args, Triple);
-
- if (CPU.empty()) {
- // We cannot link any standard libraries without an MCU specified.
- D.Diag(diag::warn_drv_avr_mcu_not_specified);
- } else {
- Optional<StringRef> FamilyName = GetMCUFamilyName(CPU);
- Optional<std::string> AVRLibcRoot = findAVRLibcInstallation();
-
- if (!FamilyName.hasValue()) {
- // We do not have an entry for this CPU in the family
- // mapping table yet.
- D.Diag(diag::warn_drv_avr_family_linking_stdlibs_not_implemented)
- << CPU;
- } else if (!GCCInstallation.isValid()) {
- // No avr-gcc found and so no runtime linked.
- D.Diag(diag::warn_drv_avr_gcc_not_found);
- } else if (!AVRLibcRoot.hasValue()) {
- // No avr-libc found and so no runtime linked.
- D.Diag(diag::warn_drv_avr_libc_not_found);
- } else { // We have enough information to link stdlibs
- std::string GCCRoot(GCCInstallation.getInstallPath());
- std::string GCCParentPath(GCCInstallation.getParentLibPath());
- std::string LibcRoot = AVRLibcRoot.getValue();
- std::string SubPath = GetMCUSubPath(CPU);
-
- getProgramPaths().push_back(GCCParentPath + "/../bin");
- getFilePaths().push_back(LibcRoot + std::string("/lib/") + SubPath);
- getFilePaths().push_back(GCCRoot + std::string("/") + SubPath);
-
- LinkStdlib = true;
- }
- }
-
- if (!LinkStdlib)
- D.Diag(diag::warn_drv_avr_stdlib_not_linked);
+ !Args.hasArg(options::OPT_nodefaultlibs) && GCCInstallation.isValid()) {
+ GCCInstallPath = GCCInstallation.getInstallPath();
+ std::string GCCParentPath(GCCInstallation.getParentLibPath());
+ getProgramPaths().push_back(GCCParentPath + "/../bin");
}
}
@@ -360,52 +387,142 @@ void AVRToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
return;
// Omit if there is no avr-libc installed.
- Optional<std::string> AVRLibcRoot = findAVRLibcInstallation();
- if (!AVRLibcRoot.hasValue())
+ std::optional<std::string> AVRLibcRoot = findAVRLibcInstallation();
+ if (!AVRLibcRoot)
return;
// Add 'avr-libc/include' to clang system include paths if applicable.
- std::string AVRInc = AVRLibcRoot.getValue() + "/include";
+ std::string AVRInc = *AVRLibcRoot + "/include";
if (llvm::sys::fs::is_directory(AVRInc))
addSystemInclude(DriverArgs, CC1Args, AVRInc);
}
+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");
+ // Use `-fno-use-cxa-atexit` as default, since avr-libc does not support
+ // `__cxa_atexit()`.
+ if (!DriverArgs.hasFlag(options::OPT_fuse_cxa_atexit,
+ options::OPT_fno_use_cxa_atexit, false))
+ CC1Args.push_back("-fno-use-cxa-atexit");
+}
+
Tool *AVRToolChain::buildLinker() const {
- return new tools::AVR::Linker(getTriple(), *this, LinkStdlib);
+ return new tools::AVR::Linker(getTriple(), *this);
+}
+
+std::string
+AVRToolChain::getCompilerRT(const llvm::opt::ArgList &Args, StringRef Component,
+ FileType Type = ToolChain::FT_Static) const {
+ assert(Type == ToolChain::FT_Static && "AVR only supports static libraries");
+ // Since AVR can never be a host environment, its compiler-rt library files
+ // should always have ".a" suffix, even on windows.
+ SmallString<32> File("/libclang_rt.");
+ File += Component.str();
+ File += ".a";
+ // Return the default compiler-rt path appended with
+ // "avr/libclang_rt.$COMPONENT.a".
+ SmallString<256> Path(ToolChain::getCompilerRTPath());
+ llvm::sys::path::append(Path, "avr");
+ llvm::sys::path::append(Path, File.str());
+ return std::string(Path);
}
void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs, const ArgList &Args,
const char *LinkingOutput) const {
+ const auto &TC = static_cast<const AVRToolChain &>(getToolChain());
+ const Driver &D = getToolChain().getDriver();
+
// Compute information about the target AVR.
- std::string CPU = getCPUName(Args, getToolChain().getTriple());
- llvm::Optional<StringRef> FamilyName = GetMCUFamilyName(CPU);
- llvm::Optional<unsigned> SectionAddressData = GetMCUSectionAddressData(CPU);
+ std::string CPU = getCPUName(D, Args, getToolChain().getTriple());
+ std::optional<StringRef> FamilyName = GetMCUFamilyName(CPU);
+ std::optional<std::string> AVRLibcRoot = TC.findAVRLibcInstallation();
+ std::optional<unsigned> SectionAddressData = GetMCUSectionAddressData(CPU);
+
+ // Compute the linker program path, and use GNU "avr-ld" as default.
+ const Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ);
+ std::string Linker = A ? getToolChain().GetLinkerPath(nullptr)
+ : getToolChain().GetProgramPath(getShortName());
- std::string Linker = getToolChain().GetProgramPath(getShortName());
ArgStringList CmdArgs;
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
// Enable garbage collection of unused sections.
- CmdArgs.push_back("--gc-sections");
+ if (!Args.hasArg(options::OPT_r))
+ CmdArgs.push_back("--gc-sections");
// Add library search paths before we specify libraries.
Args.AddAllArgs(CmdArgs, options::OPT_L);
getToolChain().AddFilePathLibArgs(Args, CmdArgs);
- if (SectionAddressData.hasValue()) {
- std::string DataSectionArg = std::string("-Tdata=0x") +
- llvm::utohexstr(SectionAddressData.getValue());
- 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;
+ // Currently we only support libgcc and compiler-rt.
+ auto RtLib = TC.GetRuntimeLibType(Args);
+ assert(
+ (RtLib == ToolChain::RLT_Libgcc || RtLib == ToolChain::RLT_CompilerRT) &&
+ "unknown runtime library");
+
+ // Only add default libraries if the user hasn't explicitly opted out.
+ bool LinkStdlib = false;
+ if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_r) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (!CPU.empty()) {
+ if (!FamilyName) {
+ // We do not have an entry for this CPU in the family
+ // mapping table yet.
+ D.Diag(diag::warn_drv_avr_family_linking_stdlibs_not_implemented)
+ << CPU;
+ } else if (!AVRLibcRoot) {
+ // No avr-libc found and so no runtime linked.
+ D.Diag(diag::warn_drv_avr_libc_not_found);
+ } else {
+ std::string SubPath = GetMCUSubPath(CPU);
+ // Add path of avr-libc.
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-L") + *AVRLibcRoot + "/lib/" + SubPath));
+ if (RtLib == ToolChain::RLT_Libgcc)
+ CmdArgs.push_back(Args.MakeArgString("-L" + TC.getGCCInstallPath() +
+ "/" + SubPath));
+ LinkStdlib = true;
+ }
+ }
+ if (!LinkStdlib)
+ D.Diag(diag::warn_drv_avr_stdlib_not_linked);
+ }
+
+ if (!Args.hasArg(options::OPT_r)) {
+ if (SectionAddressData) {
+ CmdArgs.push_back(
+ Args.MakeArgString("--defsym=__DATA_REGION_ORIGIN__=0x" +
+ Twine::utohexstr(*SectionAddressData)));
+ } else {
+ // We do not have an entry for this CPU in the address mapping table
+ // yet.
+ D.Diag(diag::warn_drv_avr_linker_section_addresses_not_implemented)
+ << CPU;
+ }
+ }
+
+ if (D.isUsingLTO()) {
+ assert(!Inputs.empty() && "Must have at least one input.");
+ // Find the first filename InputInfo object.
+ auto Input = llvm::find_if(
+ Inputs, [](const InputInfo &II) -> bool { return II.isFilename(); });
+ if (Input == Inputs.end())
+ // For a very rare case, all of the inputs to the linker are
+ // InputArg. If that happens, just use the first InputInfo.
+ Input = Inputs.begin();
+
+ addLTOOptions(TC, Args, CmdArgs, Output, *Input,
+ D.getLTOMode() == LTOK_Thin);
}
// If the family name is known, we can link with the device-specific libgcc.
@@ -414,36 +531,85 @@ 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));
- CmdArgs.push_back("-lgcc");
+ // Link to libgcc.
+ if (RtLib == ToolChain::RLT_Libgcc)
+ CmdArgs.push_back("-lgcc");
+
+ // Link to generic libraries of avr-libc.
CmdArgs.push_back("-lm");
CmdArgs.push_back("-lc");
// Add the link library specific to the MCU.
CmdArgs.push_back(Args.MakeArgString(std::string("-l") + CPU));
- // Specify the family name as the emulation mode to use.
- // This is almost always required because otherwise avr-ld
- // will assume 'avr2' and warn about the program being larger
- // than the bare minimum supports.
- CmdArgs.push_back(Args.MakeArgString(std::string("-m") + *FamilyName));
+ // Add the relocatable inputs.
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
+
+ // We directly use libclang_rt.builtins.a as input file, instead of using
+ // '-lclang_rt.builtins'.
+ if (RtLib == ToolChain::RLT_CompilerRT) {
+ std::string RtLib =
+ getToolChain().getCompilerRT(Args, "builtins", ToolChain::FT_Static);
+ if (llvm::sys::fs::exists(RtLib))
+ CmdArgs.push_back(Args.MakeArgString(RtLib));
+ }
+
+ CmdArgs.push_back("--end-group");
+
+ // Add avr-libc's linker script to lld by default, if it exists.
+ if (!Args.hasArg(options::OPT_T) &&
+ Linker.find("avr-ld") == std::string::npos) {
+ std::string Path(*AVRLibcRoot + "/lib/ldscripts/");
+ Path += *FamilyName;
+ Path += ".x";
+ if (llvm::sys::fs::exists(Path))
+ CmdArgs.push_back(Args.MakeArgString("-T" + Path));
+ }
+ // Otherwise add user specified linker script to either avr-ld or lld.
+ else
+ Args.AddAllArgs(CmdArgs, options::OPT_T);
+
+ if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true))
+ CmdArgs.push_back("--relax");
+ } else {
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
}
+ // Specify the family name as the emulation mode to use.
+ // This is almost always required because otherwise avr-ld
+ // will assume 'avr2' and warn about the program being larger
+ // than the bare minimum supports.
+ if (Linker.find("avr-ld") != std::string::npos && FamilyName)
+ CmdArgs.push_back(Args.MakeArgString(std::string("-m") + *FamilyName));
+
C.addCommand(std::make_unique<Command>(
JA, *this, ResponseFileSupport::AtFileCurCP(), Args.MakeArgString(Linker),
CmdArgs, Inputs, Output));
}
-llvm::Optional<std::string> AVRToolChain::findAVRLibcInstallation() const {
+std::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;
+ return std::nullopt;
}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/AVR.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/AVR.h
index f612aa691182..247188b7eaad 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/AVR.h
+++ b/contrib/llvm-project/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,28 +26,33 @@ 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;
+
+ std::optional<std::string> findAVRLibcInstallation() const;
+ StringRef getGCCInstallPath() const { return GCCInstallPath; }
+ std::string getCompilerRT(const llvm::opt::ArgList &Args, StringRef Component,
+ FileType Type) const override;
+
+ bool HasNativeLLVMSupport() const override { return true; }
+
protected:
Tool *buildLinker() const override;
private:
- /// Whether libgcc, libct, and friends should be linked.
- ///
- /// This is not done if the user does not specify a
- /// microcontroller on the command line.
- bool LinkStdlib;
-
- llvm::Optional<std::string> findAVRLibcInstallation() const;
+ StringRef GCCInstallPath;
};
} // end namespace toolchains
namespace tools {
namespace AVR {
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
public:
- Linker(const llvm::Triple &Triple, const ToolChain &TC, bool LinkStdlib)
- : Tool("AVR::Linker", "avr-ld", TC), Triple(Triple),
- LinkStdlib(LinkStdlib) {}
+ Linker(const llvm::Triple &Triple, const ToolChain &TC)
+ : Tool("AVR::Linker", "avr-ld", TC), Triple(Triple) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
@@ -58,7 +63,6 @@ public:
protected:
const llvm::Triple &Triple;
- bool LinkStdlib;
};
} // end namespace AVR
} // end namespace tools
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Ananas.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Ananas.cpp
deleted file mode 100644
index be1476a7636c..000000000000
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Ananas.cpp
+++ /dev/null
@@ -1,144 +0,0 @@
-//===--- Ananas.cpp - Ananas ToolChain Implementations ------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "Ananas.h"
-#include "CommonArgs.h"
-#include "clang/Driver/Compilation.h"
-#include "clang/Driver/Driver.h"
-#include "clang/Driver/InputInfo.h"
-#include "clang/Driver/Options.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/Option/ArgList.h"
-#include "llvm/Support/Path.h"
-
-using namespace clang::driver;
-using namespace clang::driver::tools;
-using namespace clang::driver::toolchains;
-using namespace clang;
-using namespace llvm::opt;
-
-void ananas::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
- claimNoWarnArgs(Args);
- ArgStringList CmdArgs;
-
- Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
-
- CmdArgs.push_back("-o");
- CmdArgs.push_back(Output.getFilename());
-
- for (const auto &II : Inputs)
- CmdArgs.push_back(II.getFilename());
-
- const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
- C.addCommand(std::make_unique<Command>(JA, *this,
- ResponseFileSupport::AtFileCurCP(),
- Exec, CmdArgs, Inputs, Output));
-}
-
-void ananas::Linker::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
- const ToolChain &ToolChain = getToolChain();
- const Driver &D = ToolChain.getDriver();
- ArgStringList CmdArgs;
-
- // 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);
-
- if (!D.SysRoot.empty())
- CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
-
- if (Args.hasArg(options::OPT_static)) {
- CmdArgs.push_back("-Bstatic");
- } else {
- if (Args.hasArg(options::OPT_rdynamic))
- CmdArgs.push_back("-export-dynamic");
- if (Args.hasArg(options::OPT_shared)) {
- CmdArgs.push_back("-Bshareable");
- } else {
- Args.AddAllArgs(CmdArgs, options::OPT_pie);
- CmdArgs.push_back("-dynamic-linker");
- CmdArgs.push_back("/lib/ld-ananas.so");
- }
- }
-
- if (Output.isFilename()) {
- CmdArgs.push_back("-o");
- CmdArgs.push_back(Output.getFilename());
- } else {
- assert(Output.isNothing() && "Invalid output.");
- }
-
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
- if (!Args.hasArg(options::OPT_shared)) {
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
- }
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
- if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) {
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbeginS.o")));
- } else {
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o")));
- }
- }
-
- Args.AddAllArgs(CmdArgs, options::OPT_L);
- ToolChain.AddFilePathLibArgs(Args, CmdArgs);
- Args.AddAllArgs(CmdArgs,
- {options::OPT_T_Group, options::OPT_e, options::OPT_s,
- options::OPT_t, options::OPT_Z_Flag, options::OPT_r});
-
- if (D.isUsingLTO()) {
- assert(!Inputs.empty() && "Must have at least one input.");
- addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs[0],
- D.getLTOMode() == LTOK_Thin);
- }
-
- AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
-
- if (ToolChain.ShouldLinkCXXStdlib(Args))
- ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
- CmdArgs.push_back("-lc");
-
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
- if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
- else
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
- }
-
- const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
- C.addCommand(std::make_unique<Command>(JA, *this,
- ResponseFileSupport::AtFileCurCP(),
- Exec, CmdArgs, Inputs, Output));
-}
-
-// Ananas - Ananas tool chain which can call as(1) and ld(1) directly.
-
-Ananas::Ananas(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
- : Generic_ELF(D, Triple, Args) {
- getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
-}
-
-Tool *Ananas::buildAssembler() const {
- return new tools::ananas::Assembler(*this);
-}
-
-Tool *Ananas::buildLinker() const { return new tools::ananas::Linker(*this); }
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Ananas.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Ananas.h
deleted file mode 100644
index 72ad3edcf056..000000000000
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Ananas.h
+++ /dev/null
@@ -1,65 +0,0 @@
-//===--- Ananas.h - Ananas ToolChain Implementations --------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ANANAS_H
-#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ANANAS_H
-
-#include "Gnu.h"
-#include "clang/Driver/Tool.h"
-#include "clang/Driver/ToolChain.h"
-
-namespace clang {
-namespace driver {
-namespace tools {
-
-/// ananas -- Directly call GNU Binutils assembler and linker
-namespace ananas {
-class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
-public:
- Assembler(const ToolChain &TC) : Tool("ananas::Assembler", "assembler", TC) {}
-
- bool hasIntegratedCPP() const override { return false; }
-
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
-};
-
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
-public:
- Linker(const ToolChain &TC) : Tool("ananas::Linker", "linker", TC) {}
-
- bool hasIntegratedCPP() const override { return false; }
- bool isLinkJob() const override { return true; }
-
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
-};
-} // end namespace ananas
-} // end namespace tools
-
-namespace toolchains {
-
-class LLVM_LIBRARY_VISIBILITY Ananas : public Generic_ELF {
-public:
- Ananas(const Driver &D, const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args);
-
-protected:
- Tool *buildAssembler() const override;
- Tool *buildLinker() const override;
-};
-
-} // end namespace toolchains
-} // end namespace driver
-} // end namespace clang
-
-#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ANANAS_H
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
index ed8c7e94b013..0cf96bb5c9cb 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
@@ -7,12 +7,13 @@
//===----------------------------------------------------------------------===//
#include "AArch64.h"
+#include "../CommonArgs.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
-#include "llvm/Support/TargetParser.h"
-#include "llvm/Support/Host.h"
+#include "llvm/TargetParser/AArch64TargetParser.h"
+#include "llvm/TargetParser/Host.h"
using namespace clang::driver;
using namespace clang::driver::tools;
@@ -37,6 +38,8 @@ std::string aarch64::getAArch64TargetCPU(const ArgList &Args,
CPU = Mcpu.split("+").first.lower();
}
+ CPU = llvm::AArch64::resolveCPUAlias(CPU);
+
// Handle CPU name is 'native'.
if (CPU == "native")
return std::string(llvm::sys::getHostCPUName());
@@ -50,13 +53,17 @@ std::string aarch64::getAArch64TargetCPU(const ArgList &Args,
return "apple-m1";
}
+ if (Triple.isXROS()) {
+ // The xrOS simulator runs on M1 as well, it should have been covered above.
+ assert(!Triple.isSimulatorEnvironment() && "xrossim should be mac-like");
+ return "apple-a12";
+ }
// arm64e requires v8.3a and only runs on apple-a12 and later CPUs.
if (Triple.isArm64e())
return "apple-a12";
- // Make sure we pick the appropriate Apple CPU if -arch is used or when
- // targetting a Darwin OS.
- if (Args.getLastArg(options::OPT_arch) || Triple.isOSDarwin())
+ // Make sure we pick the appropriate Apple CPU when targetting a Darwin OS.
+ if (Triple.isOSDarwin())
return Triple.getArch() == llvm::Triple::aarch64_32 ? "apple-s4"
: "apple-a7";
@@ -65,71 +72,68 @@ std::string aarch64::getAArch64TargetCPU(const ArgList &Args,
// Decode AArch64 features from string like +[no]featureA+[no]featureB+...
static bool DecodeAArch64Features(const Driver &D, StringRef text,
- std::vector<StringRef> &Features,
- llvm::AArch64::ArchKind ArchKind) {
+ llvm::AArch64::ExtensionSet &Extensions) {
SmallVector<StringRef, 8> Split;
text.split(Split, StringRef("+"), -1, false);
for (StringRef Feature : Split) {
- StringRef FeatureName = llvm::AArch64::getArchExtFeature(Feature);
- if (!FeatureName.empty())
- Features.push_back(FeatureName);
- else if (Feature == "neon" || Feature == "noneon")
+ if (Feature == "neon" || Feature == "noneon") {
D.Diag(clang::diag::err_drv_no_neon_modifier);
- else
+ continue;
+ }
+ if (!Extensions.parseModifier(Feature))
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 ((ArchKind == llvm::AArch64::ArchKind::ARMV8_6A ||
- ArchKind == llvm::AArch64::ArchKind::ARMV8_7A) && Feature == "sve")
- Features.push_back("+f32mm");
}
+
return true;
}
// Check if the CPU name and feature modifiers in -mcpu are legal. If yes,
// decode CPU and feature.
static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
- std::vector<StringRef> &Features) {
+ llvm::AArch64::ExtensionSet &Extensions) {
std::pair<StringRef, StringRef> Split = Mcpu.split("+");
CPU = Split.first;
- llvm::AArch64::ArchKind ArchKind = llvm::AArch64::ArchKind::ARMV8A;
if (CPU == "native")
CPU = llvm::sys::getHostCPUName();
if (CPU == "generic") {
- Features.push_back("+neon");
+ Extensions.enable(llvm::AArch64::AEK_SIMD);
} else {
- ArchKind = llvm::AArch64::parseCPUArch(CPU);
- if (!llvm::AArch64::getArchFeatures(ArchKind, Features))
+ const std::optional<llvm::AArch64::CpuInfo> CpuInfo =
+ llvm::AArch64::parseCpu(CPU);
+ if (!CpuInfo)
return false;
- uint64_t Extension = llvm::AArch64::getDefaultExtensions(CPU, ArchKind);
- if (!llvm::AArch64::getExtensionFeatures(Extension, Features))
- return false;
- }
+ Extensions.addCPUDefaults(*CpuInfo);
+ }
- if (Split.second.size() &&
- !DecodeAArch64Features(D, Split.second, Features, ArchKind))
- return false;
+ if (Split.second.size() &&
+ !DecodeAArch64Features(D, Split.second, Extensions))
+ return false;
- return true;
+ return true;
}
static bool
getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
const ArgList &Args,
- std::vector<StringRef> &Features) {
+ llvm::AArch64::ExtensionSet &Extensions) {
std::string MarchLowerCase = March.lower();
std::pair<StringRef, StringRef> Split = StringRef(MarchLowerCase).split("+");
- llvm::AArch64::ArchKind ArchKind = llvm::AArch64::parseArch(Split.first);
- if (ArchKind == llvm::AArch64::ArchKind::INVALID ||
- !llvm::AArch64::getArchFeatures(ArchKind, Features) ||
- (Split.second.size() &&
- !DecodeAArch64Features(D, Split.second, Features, ArchKind)))
+ const llvm::AArch64::ArchInfo *ArchInfo =
+ llvm::AArch64::parseArch(Split.first);
+ if (Split.first == "native")
+ ArchInfo = llvm::AArch64::getArchForCpu(llvm::sys::getHostCPUName().str());
+ if (!ArchInfo)
+ return false;
+
+ Extensions.addArchDefaults(*ArchInfo);
+
+ if ((Split.second.size() &&
+ !DecodeAArch64Features(D, Split.second, Extensions)))
return false;
return true;
@@ -138,10 +142,10 @@ getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
static bool
getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
const ArgList &Args,
- std::vector<StringRef> &Features) {
+ llvm::AArch64::ExtensionSet &Extensions) {
StringRef CPU;
std::string McpuLowerCase = Mcpu.lower();
- if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, Features))
+ if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, Extensions))
return false;
return true;
@@ -152,17 +156,17 @@ getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,
const ArgList &Args,
std::vector<StringRef> &Features) {
std::string MtuneLowerCase = Mtune.lower();
- // Check CPU name is valid
- std::vector<StringRef> MtuneFeatures;
+ // Check CPU name is valid, but ignore any extensions on it.
+ llvm::AArch64::ExtensionSet Extensions;
StringRef Tune;
- if (!DecodeAArch64Mcpu(D, MtuneLowerCase, Tune, MtuneFeatures))
+ if (!DecodeAArch64Mcpu(D, MtuneLowerCase, Tune, Extensions))
return false;
// Handle CPU name is 'native'.
if (MtuneLowerCase == "native")
MtuneLowerCase = std::string(llvm::sys::getHostCPUName());
if (MtuneLowerCase == "cyclone" ||
- StringRef(MtuneLowerCase).startswith("apple")) {
+ StringRef(MtuneLowerCase).starts_with("apple")) {
Features.push_back("+zcm");
Features.push_back("+zcz");
}
@@ -174,7 +178,8 @@ getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
const ArgList &Args,
std::vector<StringRef> &Features) {
StringRef CPU;
- std::vector<StringRef> DecodedFeature;
+ // Check CPU name is valid, but ignore any extensions on it.
+ llvm::AArch64::ExtensionSet DecodedFeature;
std::string McpuLowerCase = Mcpu.lower();
if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, DecodedFeature))
return false;
@@ -189,27 +194,31 @@ void aarch64::getAArch64TargetFeatures(const Driver &D,
bool ForAS) {
Arg *A;
bool success = true;
- // Enable NEON by default.
- Features.push_back("+neon");
- llvm::StringRef WaMArch = "";
+ llvm::StringRef WaMArch;
+ llvm::AArch64::ExtensionSet Extensions;
if (ForAS)
for (const auto *A :
Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler))
for (StringRef Value : A->getValues())
- if (Value.startswith("-march="))
+ if (Value.starts_with("-march="))
WaMArch = Value.substr(7);
// Call getAArch64ArchFeaturesFromMarch only if "-Wa,-march=" or
// "-Xassembler -march" is detected. Otherwise it may return false
// and causes Clang to error out.
- if (WaMArch.size())
- success = getAArch64ArchFeaturesFromMarch(D, WaMArch, Args, Features);
+ if (!WaMArch.empty())
+ success = getAArch64ArchFeaturesFromMarch(D, WaMArch, Args, Extensions);
else if ((A = Args.getLastArg(options::OPT_march_EQ)))
- success = getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Features);
+ success =
+ getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Extensions);
else if ((A = Args.getLastArg(options::OPT_mcpu_EQ)))
- success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
- else if (Args.hasArg(options::OPT_arch) || isCPUDeterminedByTriple(Triple))
+ success =
+ getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Extensions);
+ else if (isCPUDeterminedByTriple(Triple))
success = getAArch64ArchFeaturesFromMcpu(
- D, getAArch64TargetCPU(Args, Triple, A), Args, Features);
+ D, getAArch64TargetCPU(Args, Triple, A), Args, Extensions);
+ else
+ // Default to 'A' profile if the architecture is not specified.
+ success = getAArch64ArchFeaturesFromMarch(D, "armv8-a", Args, Extensions);
if (success && (A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)))
success =
@@ -217,29 +226,48 @@ void aarch64::getAArch64TargetFeatures(const Driver &D,
else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ)))
success =
getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
- else if (success &&
- (Args.hasArg(options::OPT_arch) || isCPUDeterminedByTriple(Triple)))
+ else if (success && isCPUDeterminedByTriple(Triple))
success = getAArch64MicroArchFeaturesFromMcpu(
D, getAArch64TargetCPU(Args, Triple, A), Args, Features);
- if (!success)
- D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ if (!success) {
+ auto Diag = D.Diag(diag::err_drv_unsupported_option_argument);
+ // If "-Wa,-march=" is used, 'WaMArch' will contain the argument's value,
+ // while 'A' is uninitialized. Only dereference 'A' in the other case.
+ if (!WaMArch.empty())
+ Diag << "-march=" << WaMArch;
+ else
+ Diag << A->getSpelling() << A->getValue();
+ }
+ // -mgeneral-regs-only disables all floating-point features.
if (Args.getLastArg(options::OPT_mgeneral_regs_only)) {
- Features.push_back("-fp-armv8");
- Features.push_back("-crypto");
- Features.push_back("-neon");
+ Extensions.disable(llvm::AArch64::AEK_FP);
+ }
+
+ // En/disable crc
+ if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {
+ if (A->getOption().matches(options::OPT_mcrc))
+ Extensions.enable(llvm::AArch64::AEK_CRC);
+ else
+ Extensions.disable(llvm::AArch64::AEK_CRC);
}
+ // At this point all hardware features are decided, so convert the extensions
+ // set to a feature list.
+ Extensions.toLLVMFeatureList(Features);
+
if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) {
StringRef Mtp = A->getValue();
- if (Mtp == "el3")
+ if (Mtp == "el3" || Mtp == "tpidr_el3")
Features.push_back("+tpidr-el3");
- else if (Mtp == "el2")
+ else if (Mtp == "el2" || Mtp == "tpidr_el2")
Features.push_back("+tpidr-el2");
- else if (Mtp == "el1")
+ else if (Mtp == "el1" || Mtp == "tpidr_el1")
Features.push_back("+tpidr-el1");
- else if (Mtp != "el0")
+ else if (Mtp == "tpidrro_el0")
+ Features.push_back("+tpidrro-el0");
+ else if (Mtp != "el0" && Mtp != "tpidr_el0")
D.Diag(diag::err_drv_invalid_mtp) << A->getAsString(Args);
}
@@ -275,8 +303,8 @@ void aarch64::getAArch64TargetFeatures(const Driver &D,
DisableComdat = true;
continue;
}
- D.Diag(diag::err_invalid_sls_hardening)
- << Scope << A->getAsString(Args);
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getSpelling() << Scope;
break;
}
}
@@ -290,124 +318,6 @@ void aarch64::getAArch64TargetFeatures(const Driver &D,
}
}
- // En/disable crc
- if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {
- if (A->getOption().matches(options::OPT_mcrc))
- Features.push_back("+crc");
- else
- Features.push_back("-crc");
- }
-
- // Handle (arch-dependent) fp16fml/fullfp16 relationship.
- // FIXME: this fp16fml option handling will be reimplemented after the
- // TargetParser rewrite.
- const auto ItRNoFullFP16 = std::find(Features.rbegin(), Features.rend(), "-fullfp16");
- const auto ItRFP16FML = std::find(Features.rbegin(), Features.rend(), "+fp16fml");
- if (llvm::is_contained(Features, "+v8.4a")) {
- const auto ItRFullFP16 = std::find(Features.rbegin(), Features.rend(), "+fullfp16");
- if (ItRFullFP16 < ItRNoFullFP16 && ItRFullFP16 < ItRFP16FML) {
- // Only entangled feature that can be to the right of this +fullfp16 is -fp16fml.
- // Only append the +fp16fml if there is no -fp16fml after the +fullfp16.
- if (std::find(Features.rbegin(), ItRFullFP16, "-fp16fml") == ItRFullFP16)
- Features.push_back("+fp16fml");
- }
- else
- goto fp16_fml_fallthrough;
- } else {
-fp16_fml_fallthrough:
- // In both of these cases, putting the 'other' feature on the end of the vector will
- // result in the same effect as placing it immediately after the current feature.
- if (ItRNoFullFP16 < ItRFP16FML)
- Features.push_back("-fp16fml");
- else if (ItRNoFullFP16 > ItRFP16FML)
- Features.push_back("+fullfp16");
- }
-
- // FIXME: this needs reimplementation too after the TargetParser rewrite
- //
- // Context sensitive meaning of Crypto:
- // 1) For Arch >= ARMv8.4a: crypto = sm4 + sha3 + sha2 + aes
- // 2) For Arch <= ARMv8.3a: crypto = sha2 + aes
- const auto ItBegin = Features.begin();
- const auto ItEnd = Features.end();
- const auto ItRBegin = Features.rbegin();
- const auto ItREnd = Features.rend();
- const auto ItRCrypto = std::find(ItRBegin, ItREnd, "+crypto");
- const auto ItRNoCrypto = std::find(ItRBegin, ItREnd, "-crypto");
- const auto HasCrypto = ItRCrypto != ItREnd;
- const auto HasNoCrypto = ItRNoCrypto != ItREnd;
- const ptrdiff_t PosCrypto = ItRCrypto - ItRBegin;
- const ptrdiff_t PosNoCrypto = ItRNoCrypto - ItRBegin;
-
- bool NoCrypto = false;
- if (HasCrypto && HasNoCrypto) {
- if (PosNoCrypto < PosCrypto)
- NoCrypto = true;
- }
-
- if (std::find(ItBegin, ItEnd, "+v8.4a") != ItEnd) {
- if (HasCrypto && !NoCrypto) {
- // Check if we have NOT disabled an algorithm with something like:
- // +crypto, -algorithm
- // And if "-algorithm" does not occur, we enable that crypto algorithm.
- const bool HasSM4 = (std::find(ItBegin, ItEnd, "-sm4") == ItEnd);
- const bool HasSHA3 = (std::find(ItBegin, ItEnd, "-sha3") == ItEnd);
- const bool HasSHA2 = (std::find(ItBegin, ItEnd, "-sha2") == ItEnd);
- const bool HasAES = (std::find(ItBegin, ItEnd, "-aes") == ItEnd);
- if (HasSM4)
- Features.push_back("+sm4");
- if (HasSHA3)
- Features.push_back("+sha3");
- if (HasSHA2)
- Features.push_back("+sha2");
- if (HasAES)
- Features.push_back("+aes");
- } else if (HasNoCrypto) {
- // Check if we have NOT enabled a crypto algorithm with something like:
- // -crypto, +algorithm
- // And if "+algorithm" does not occur, we disable that crypto algorithm.
- const bool HasSM4 = (std::find(ItBegin, ItEnd, "+sm4") != ItEnd);
- const bool HasSHA3 = (std::find(ItBegin, ItEnd, "+sha3") != ItEnd);
- const bool HasSHA2 = (std::find(ItBegin, ItEnd, "+sha2") != ItEnd);
- const bool HasAES = (std::find(ItBegin, ItEnd, "+aes") != ItEnd);
- if (!HasSM4)
- Features.push_back("-sm4");
- if (!HasSHA3)
- Features.push_back("-sha3");
- if (!HasSHA2)
- Features.push_back("-sha2");
- if (!HasAES)
- Features.push_back("-aes");
- }
- } else {
- if (HasCrypto && !NoCrypto) {
- const bool HasSHA2 = (std::find(ItBegin, ItEnd, "-sha2") == ItEnd);
- const bool HasAES = (std::find(ItBegin, ItEnd, "-aes") == ItEnd);
- if (HasSHA2)
- Features.push_back("+sha2");
- if (HasAES)
- Features.push_back("+aes");
- } else if (HasNoCrypto) {
- const bool HasSHA2 = (std::find(ItBegin, ItEnd, "+sha2") != ItEnd);
- const bool HasAES = (std::find(ItBegin, ItEnd, "+aes") != ItEnd);
- const bool HasV82a = (std::find(ItBegin, ItEnd, "+v8.2a") != ItEnd);
- const bool HasV83a = (std::find(ItBegin, ItEnd, "+v8.3a") != ItEnd);
- const bool HasV84a = (std::find(ItBegin, ItEnd, "+v8.4a") != ItEnd);
- if (!HasSHA2)
- Features.push_back("-sha2");
- if (!HasAES)
- Features.push_back("-aes");
- if (HasV82a || HasV83a || HasV84a) {
- Features.push_back("-sm4");
- Features.push_back("-sha3");
- }
- }
- }
-
- auto V8_6Pos = llvm::find(Features, "+v8.6a");
- if (V8_6Pos != std::end(Features))
- V8_6Pos = Features.insert(std::next(V8_6Pos), {"+i8mm", "+bf16"});
-
if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
options::OPT_munaligned_access)) {
if (A->getOption().matches(options::OPT_mno_unaligned_access))
@@ -519,4 +429,22 @@ fp16_fml_fallthrough:
if (Args.hasArg(options::OPT_mno_neg_immediates))
Features.push_back("+no-neg-immediates");
+
+ if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a53_835769,
+ options::OPT_mno_fix_cortex_a53_835769)) {
+ if (A->getOption().matches(options::OPT_mfix_cortex_a53_835769))
+ Features.push_back("+fix-cortex-a53-835769");
+ else
+ Features.push_back("-fix-cortex-a53-835769");
+ } else if (Triple.isAndroid() || Triple.isOHOSFamily()) {
+ // Enabled A53 errata (835769) workaround by default on android
+ Features.push_back("+fix-cortex-a53-835769");
+ } else if (Triple.isOSFuchsia()) {
+ std::string CPU = getCPUName(D, Args, Triple);
+ if (CPU.empty() || CPU == "generic" || CPU == "cortex-a53")
+ Features.push_back("+fix-cortex-a53-835769");
+ }
+
+ if (Args.getLastArg(options::OPT_mno_bti_at_return_twice))
+ Features.push_back("+no-bti-at-return-twice");
}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/ARM.cpp
index 4ab547fabe43..e6ee2f88a84e 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -12,8 +12,8 @@
#include "clang/Driver/Options.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/ArgList.h"
-#include "llvm/Support/TargetParser.h"
-#include "llvm/Support/Host.h"
+#include "llvm/TargetParser/ARMTargetParser.h"
+#include "llvm/TargetParser/Host.h"
using namespace clang::driver;
using namespace clang::driver::tools;
@@ -32,6 +32,20 @@ bool arm::isARMMProfile(const llvm::Triple &Triple) {
return llvm::ARM::parseArchProfile(Arch) == llvm::ARM::ProfileKind::M;
}
+// On Arm the endianness of the output file is determined by the target and
+// can be overridden by the pseudo-target flags '-mlittle-endian'/'-EL' and
+// '-mbig-endian'/'-EB'. Unlike other targets the flag does not result in a
+// normalized triple so we must handle the flag here.
+bool arm::isARMBigEndian(const llvm::Triple &Triple, const ArgList &Args) {
+ if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
+ options::OPT_mbig_endian)) {
+ return !A->getOption().matches(options::OPT_mlittle_endian);
+ }
+
+ return Triple.getArch() == llvm::Triple::armeb ||
+ Triple.getArch() == llvm::Triple::thumbeb;
+}
+
// True if A-profile.
bool arm::isARMAProfile(const llvm::Triple &Triple) {
llvm::StringRef Arch = Triple.getArchName();
@@ -53,9 +67,9 @@ void arm::getARMArchCPUFromArgs(const ArgList &Args, llvm::StringRef &Arch,
// Use getValues because -Wa can have multiple arguments
// e.g. -Wa,-mcpu=foo,-mcpu=bar
for (StringRef Value : A->getValues()) {
- if (Value.startswith("-mcpu="))
+ if (Value.starts_with("-mcpu="))
CPU = Value.substr(6);
- if (Value.startswith("-march="))
+ if (Value.starts_with("-march="))
Arch = Value.substr(7);
}
}
@@ -72,25 +86,25 @@ static void getARMHWDivFeatures(const Driver &D, const Arg *A,
}
// Handle -mfpu=.
-static unsigned getARMFPUFeatures(const Driver &D, const Arg *A,
- const ArgList &Args, StringRef FPU,
- std::vector<StringRef> &Features) {
- unsigned FPUID = llvm::ARM::parseFPU(FPU);
- if (!llvm::ARM::getFPUFeatures(FPUID, Features))
+static llvm::ARM::FPUKind getARMFPUFeatures(const Driver &D, const Arg *A,
+ const ArgList &Args, StringRef FPU,
+ std::vector<StringRef> &Features) {
+ llvm::ARM::FPUKind FPUKind = llvm::ARM::parseFPU(FPU);
+ if (!llvm::ARM::getFPUFeatures(FPUKind, Features))
D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
- return FPUID;
+ return FPUKind;
}
// Decode ARM features from string like +[no]featureA+[no]featureB+...
static bool DecodeARMFeatures(const Driver &D, StringRef text, StringRef CPU,
llvm::ARM::ArchKind ArchKind,
std::vector<StringRef> &Features,
- unsigned &ArgFPUID) {
+ llvm::ARM::FPUKind &ArgFPUKind) {
SmallVector<StringRef, 8> Split;
text.split(Split, StringRef("+"), -1, false);
for (StringRef Feature : Split) {
- if (!appendArchExtFeatures(CPU, ArchKind, Feature, Features, ArgFPUID))
+ if (!appendArchExtFeatures(CPU, ArchKind, Feature, Features, ArgFPUKind))
return false;
}
return true;
@@ -112,31 +126,52 @@ static void DecodeARMFeaturesFromCPU(const Driver &D, StringRef CPU,
static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args,
llvm::StringRef ArchName, llvm::StringRef CPUName,
std::vector<StringRef> &Features,
- const llvm::Triple &Triple, unsigned &ArgFPUID) {
+ const llvm::Triple &Triple,
+ llvm::ARM::FPUKind &ArgFPUKind) {
std::pair<StringRef, StringRef> Split = ArchName.split("+");
std::string MArch = arm::getARMArch(ArchName, Triple);
llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(MArch);
if (ArchKind == llvm::ARM::ArchKind::INVALID ||
- (Split.second.size() && !DecodeARMFeatures(D, Split.second, CPUName,
- ArchKind, Features, ArgFPUID)))
- D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ (Split.second.size() &&
+ !DecodeARMFeatures(D, Split.second, CPUName, ArchKind, Features,
+ ArgFPUKind)))
+ D.Diag(clang::diag::err_drv_unsupported_option_argument)
+ << A->getSpelling() << A->getValue();
}
// Check -mcpu=. Needs ArchName to handle -mcpu=generic.
static void checkARMCPUName(const Driver &D, const Arg *A, const ArgList &Args,
llvm::StringRef CPUName, llvm::StringRef ArchName,
std::vector<StringRef> &Features,
- const llvm::Triple &Triple, unsigned &ArgFPUID) {
+ const llvm::Triple &Triple,
+ llvm::ARM::FPUKind &ArgFPUKind) {
std::pair<StringRef, StringRef> Split = CPUName.split("+");
std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple);
llvm::ARM::ArchKind ArchKind =
arm::getLLVMArchKindForARM(CPU, ArchName, Triple);
if (ArchKind == llvm::ARM::ArchKind::INVALID ||
- (Split.second.size() &&
- !DecodeARMFeatures(D, Split.second, CPU, ArchKind, Features, ArgFPUID)))
- D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ (Split.second.size() && !DecodeARMFeatures(D, Split.second, CPU, ArchKind,
+ Features, ArgFPUKind)))
+ D.Diag(clang::diag::err_drv_unsupported_option_argument)
+ << A->getSpelling() << A->getValue();
+}
+
+// If -mfloat-abi=hard or -mhard-float are specified explicitly then check that
+// floating point registers are available on the target CPU.
+static void checkARMFloatABI(const Driver &D, const ArgList &Args,
+ bool HasFPRegs) {
+ if (HasFPRegs)
+ return;
+ const Arg *A =
+ Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
+ options::OPT_mfloat_abi_EQ);
+ if (A && (A->getOption().matches(options::OPT_mhard_float) ||
+ (A->getOption().matches(options::OPT_mfloat_abi_EQ) &&
+ A->getValue() == StringRef("hard"))))
+ D.Diag(clang::diag::warn_drv_no_floating_point_registers)
+ << A->getAsString(Args);
}
bool arm::useAAPCSForMachO(const llvm::Triple &T) {
@@ -147,14 +182,35 @@ bool arm::useAAPCSForMachO(const llvm::Triple &T) {
T.getOS() == llvm::Triple::UnknownOS || isARMMProfile(T);
}
+// We follow GCC and support when the backend has support for the MRC/MCR
+// instructions that are used to set the hard thread pointer ("CP15 C13
+// Thread id").
+bool arm::isHardTPSupported(const llvm::Triple &Triple) {
+ int Ver = getARMSubArchVersionNumber(Triple);
+ llvm::ARM::ArchKind AK = llvm::ARM::parseArch(Triple.getArchName());
+ return Triple.isARM() || AK == llvm::ARM::ArchKind::ARMV6T2 ||
+ (Ver >= 7 && AK != llvm::ARM::ArchKind::ARMV8MBaseline);
+}
+
// 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, bool ForAS) {
if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) {
arm::ReadTPMode ThreadPointer =
llvm::StringSwitch<arm::ReadTPMode>(A->getValue())
- .Case("cp15", ReadTPMode::Cp15)
+ .Case("cp15", ReadTPMode::TPIDRURO)
+ .Case("tpidrurw", ReadTPMode::TPIDRURW)
+ .Case("tpidruro", ReadTPMode::TPIDRURO)
+ .Case("tpidrprw", ReadTPMode::TPIDRPRW)
.Case("soft", ReadTPMode::Soft)
.Default(ReadTPMode::Invalid);
+ if ((ThreadPointer == ReadTPMode::TPIDRURW ||
+ ThreadPointer == ReadTPMode::TPIDRURO ||
+ ThreadPointer == ReadTPMode::TPIDRPRW) &&
+ !isHardTPSupported(Triple) && !ForAS) {
+ D.Diag(diag::err_target_unsupported_tp_hard) << Triple.getArchName();
+ return ReadTPMode::Invalid;
+ }
if (ThreadPointer != ReadTPMode::Invalid)
return ThreadPointer;
if (StringRef(A->getValue()).empty())
@@ -229,9 +285,9 @@ void arm::setArchNameInTriple(const Driver &D, const ArgList &Args,
// There is no assembler equivalent of -mno-thumb, -marm, or -mno-arm.
if (Value == "-mthumb")
IsThumb = true;
- else if (Value.startswith("-march="))
+ else if (Value.starts_with("-march="))
WaMArch = Value.substr(7);
- else if (Value.startswith("-mcpu="))
+ else if (Value.starts_with("-mcpu="))
WaMCPU = Value.substr(6);
}
}
@@ -257,6 +313,11 @@ void arm::setArchNameInTriple(const Driver &D, const ArgList &Args,
void arm::setFloatABIInTriple(const Driver &D, const ArgList &Args,
llvm::Triple &Triple) {
+ if (Triple.isOSLiteOS()) {
+ Triple.setEnvironment(llvm::Triple::OpenHOS);
+ return;
+ }
+
bool isHardFloat =
(arm::getARMFloatABI(D, Triple, Args) == arm::FloatABI::Hard);
@@ -276,6 +337,8 @@ void arm::setFloatABIInTriple(const Driver &D, const ArgList &Args,
Triple.setEnvironment(isHardFloat ? llvm::Triple::MuslEABIHF
: llvm::Triple::MuslEABI);
break;
+ case llvm::Triple::OpenHOS:
+ break;
default: {
arm::FloatABI DefaultABI = arm::getDefaultFloatABI(Triple);
if (DefaultABI != arm::FloatABI::Invalid &&
@@ -303,6 +366,8 @@ arm::FloatABI arm::getDefaultFloatABI(const llvm::Triple &Triple) {
case llvm::Triple::MacOSX:
case llvm::Triple::IOS:
case llvm::Triple::TvOS:
+ case llvm::Triple::DriverKit:
+ case llvm::Triple::XROS:
// Darwin defaults to "softfp" for v6 and v7.
if (Triple.isWatchABI())
return FloatABI::Hard;
@@ -314,6 +379,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:
@@ -336,10 +405,13 @@ arm::FloatABI arm::getDefaultFloatABI(const llvm::Triple &Triple) {
}
break;
+ case llvm::Triple::Haiku:
case llvm::Triple::OpenBSD:
return FloatABI::SoftFP;
default:
+ if (Triple.isOHOSFamily())
+ return FloatABI::Soft;
switch (Triple.getEnvironment()) {
case llvm::Triple::GNUEABIHF:
case llvm::Triple::MuslEABIHF:
@@ -412,15 +484,15 @@ static bool hasIntegerMVE(const std::vector<StringRef> &F) {
(NoMVE == F.rend() || std::distance(MVE, NoMVE) > 0);
}
-void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
- const ArgList &Args, ArgStringList &CmdArgs,
- std::vector<StringRef> &Features, bool ForAS) {
+llvm::ARM::FPUKind arm::getARMTargetFeatures(const Driver &D,
+ const llvm::Triple &Triple,
+ const ArgList &Args,
+ std::vector<StringRef> &Features,
+ bool ForAS, bool ForMultilib) {
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);
- llvm::Optional<std::pair<const Arg *, StringRef>> WaCPU, WaFPU, WaHDiv,
- WaArch;
+ std::optional<std::pair<const Arg *, StringRef>> WaCPU, WaFPU, WaHDiv, WaArch;
// This vector will accumulate features from the architecture
// extension suffixes on -mcpu and -march (e.g. the 'bar' in
@@ -457,28 +529,38 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
// We use getValues here because you can have many options per -Wa
// We will keep the last one we find for each of these
for (StringRef Value : A->getValues()) {
- if (Value.startswith("-mfpu=")) {
+ if (Value.starts_with("-mfpu=")) {
WaFPU = std::make_pair(A, Value.substr(6));
- } else if (Value.startswith("-mcpu=")) {
+ } else if (Value.starts_with("-mcpu=")) {
WaCPU = std::make_pair(A, Value.substr(6));
- } else if (Value.startswith("-mhwdiv=")) {
+ } else if (Value.starts_with("-mhwdiv=")) {
WaHDiv = std::make_pair(A, Value.substr(8));
- } else if (Value.startswith("-march=")) {
+ } else if (Value.starts_with("-march=")) {
WaArch = std::make_pair(A, Value.substr(7));
}
}
}
+
+ // The integrated assembler doesn't implement e_flags setting behavior for
+ // -meabi=gnu (gcc -mabi={apcs-gnu,atpcs} passes -meabi=gnu to gas). For
+ // compatibility we accept but warn.
+ if (Arg *A = Args.getLastArgNoClaim(options::OPT_mabi_EQ))
+ A->ignoreTargetSpecific();
}
- if (ThreadPointer == arm::ReadTPMode::Cp15)
- Features.push_back("+read-tp-hard");
+ if (getReadTPMode(D, Args, Triple, ForAS) == ReadTPMode::TPIDRURW)
+ Features.push_back("+read-tp-tpidrurw");
+ if (getReadTPMode(D, Args, Triple, ForAS) == ReadTPMode::TPIDRURO)
+ Features.push_back("+read-tp-tpidruro");
+ if (getReadTPMode(D, Args, Triple, ForAS) == ReadTPMode::TPIDRPRW)
+ Features.push_back("+read-tp-tpidrprw");
const Arg *ArchArg = Args.getLastArg(options::OPT_march_EQ);
const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ);
StringRef ArchName;
StringRef CPUName;
- unsigned ArchArgFPUID = llvm::ARM::FK_INVALID;
- unsigned CPUArgFPUID = llvm::ARM::FK_INVALID;
+ llvm::ARM::FPUKind ArchArgFPUKind = llvm::ARM::FK_INVALID;
+ llvm::ARM::FPUKind CPUArgFPUKind = llvm::ARM::FK_INVALID;
// Check -mcpu. ClangAs gives preference to -Wa,-mcpu=.
if (WaCPU) {
@@ -498,13 +580,13 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
ArchName = WaArch->second;
// This will set any features after the base architecture.
checkARMArchName(D, WaArch->first, Args, ArchName, CPUName,
- ExtensionFeatures, Triple, ArchArgFPUID);
+ ExtensionFeatures, Triple, ArchArgFPUKind);
// The base architecture was handled in ToolChain::ComputeLLVMTriple because
// triple is read only by this point.
} else if (ArchArg) {
ArchName = ArchArg->getValue();
checkARMArchName(D, ArchArg, Args, ArchName, CPUName, ExtensionFeatures,
- Triple, ArchArgFPUID);
+ Triple, ArchArgFPUKind);
}
// Add CPU features for generic CPUs
@@ -524,9 +606,14 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
if (CPUArg)
checkARMCPUName(D, CPUArg, Args, CPUName, ArchName, ExtensionFeatures,
- Triple, CPUArgFPUID);
+ Triple, CPUArgFPUKind);
+
+ // TODO Handle -mtune=. Suppress -Wunused-command-line-argument as a
+ // longstanding behavior.
+ (void)Args.getLastArg(options::OPT_mtune_EQ);
+
// Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=.
- unsigned FPUID = llvm::ARM::FK_INVALID;
+ llvm::ARM::FPUKind FPUKind = llvm::ARM::FK_INVALID;
const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ);
if (WaFPU) {
if (FPUArg)
@@ -534,20 +621,25 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
<< FPUArg->getAsString(Args);
(void)getARMFPUFeatures(D, WaFPU->first, Args, WaFPU->second, Features);
} else if (FPUArg) {
- FPUID = getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features);
+ FPUKind = getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features);
} else if (Triple.isAndroid() && getARMSubArchVersionNumber(Triple) >= 7) {
const char *AndroidFPU = "neon";
- FPUID = llvm::ARM::parseFPU(AndroidFPU);
- if (!llvm::ARM::getFPUFeatures(FPUID, Features))
+ FPUKind = llvm::ARM::parseFPU(AndroidFPU);
+ if (!llvm::ARM::getFPUFeatures(FPUKind, Features))
D.Diag(clang::diag::err_drv_clang_unsupported)
<< std::string("-mfpu=") + AndroidFPU;
+ } else if (ArchArgFPUKind != llvm::ARM::FK_INVALID ||
+ CPUArgFPUKind != llvm::ARM::FK_INVALID) {
+ FPUKind =
+ CPUArgFPUKind != llvm::ARM::FK_INVALID ? CPUArgFPUKind : ArchArgFPUKind;
+ (void)llvm::ARM::getFPUFeatures(FPUKind, Features);
} else {
if (!ForAS) {
std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple);
llvm::ARM::ArchKind ArchKind =
arm::getLLVMArchKindForARM(CPU, ArchName, Triple);
- FPUID = llvm::ARM::getDefaultFPU(CPU, ArchKind);
- (void)llvm::ARM::getFPUFeatures(FPUID, Features);
+ FPUKind = llvm::ARM::getDefaultFPU(CPU, ArchKind);
+ (void)llvm::ARM::getFPUFeatures(FPUKind, Features);
}
}
@@ -598,25 +690,30 @@ fp16_fml_fallthrough:
// -march/-mcpu effectively disables the FPU (GCC ignores the -mfpu options in
// this case). Note that the ABI can also be set implicitly by the target
// selected.
+ bool HasFPRegs = true;
if (ABI == arm::FloatABI::Soft) {
llvm::ARM::getFPUFeatures(llvm::ARM::FK_NONE, Features);
// Disable all features relating to hardware FP, not already disabled by the
// above call.
- Features.insert(Features.end(), {"-dotprod", "-fp16fml", "-bf16", "-mve",
- "-mve.fp", "-fpregs"});
- } else if (FPUID == llvm::ARM::FK_NONE ||
- ArchArgFPUID == llvm::ARM::FK_NONE ||
- CPUArgFPUID == llvm::ARM::FK_NONE) {
+ Features.insert(Features.end(),
+ {"-dotprod", "-fp16fml", "-bf16", "-mve", "-mve.fp"});
+ HasFPRegs = false;
+ FPUKind = llvm::ARM::FK_NONE;
+ } else if (FPUKind == llvm::ARM::FK_NONE ||
+ ArchArgFPUKind == llvm::ARM::FK_NONE ||
+ CPUArgFPUKind == llvm::ARM::FK_NONE) {
// -mfpu=none, -march=armvX+nofp or -mcpu=X+nofp is *very* similar to
// -mfloat-abi=soft, only that it should not disable MVE-I. They disable the
// FPU, but not the FPU registers, thus MVE-I, which depends only on the
// latter, is still supported.
Features.insert(Features.end(),
{"-dotprod", "-fp16fml", "-bf16", "-mve.fp"});
- if (!hasIntegerMVE(Features))
- Features.emplace_back("-fpregs");
+ HasFPRegs = hasIntegerMVE(Features);
+ FPUKind = llvm::ARM::FK_NONE;
}
+ if (!HasFPRegs)
+ Features.emplace_back("-fpregs");
// En/disable crc code generation.
if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {
@@ -697,10 +794,41 @@ fp16_fml_fallthrough:
}
}
+ // Propagate frame-chain model selection
+ if (Arg *A = Args.getLastArg(options::OPT_mframe_chain)) {
+ StringRef FrameChainOption = A->getValue();
+ if (FrameChainOption.starts_with("aapcs"))
+ Features.push_back("+aapcs-frame-chain");
+ if (FrameChainOption == "aapcs+leaf")
+ Features.push_back("+aapcs-frame-chain-leaf");
+ }
+
// CMSE: Check for target 8M (for -mcmse to be applicable) is performed later.
if (Args.getLastArg(options::OPT_mcmse))
Features.push_back("+8msecext");
+ 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");
+ }
+
+ // This also handles the -m(no-)fix-cortex-a72-1655431 arguments via aliases.
+ if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a57_aes_1742098,
+ options::OPT_mno_fix_cortex_a57_aes_1742098)) {
+ if (A->getOption().matches(options::OPT_mfix_cortex_a57_aes_1742098)) {
+ Features.push_back("+fix-cortex-a57-aes-1742098");
+ } else {
+ Features.push_back("-fix-cortex-a57-aes-1742098");
+ }
+ }
+
// Look for the last occurrence of -mlong-calls or -mno-long-calls. If
// neither options are specified, see if we are compiling for kernel/kext and
// decide whether to pass "+long-calls" based on the OS and its version.
@@ -709,39 +837,42 @@ fp16_fml_fallthrough:
if (A->getOption().matches(options::OPT_mlong_calls))
Features.push_back("+long-calls");
} else if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6)) &&
- !Triple.isWatchOS()) {
- Features.push_back("+long-calls");
+ !Triple.isWatchOS() && !Triple.isXROS()) {
+ Features.push_back("+long-calls");
}
// Generate execute-only output (no data access to code sections).
// This only makes sense for the compiler, not for the assembler.
- if (!ForAS) {
+ // It's not needed for multilib selection and may hide an unused
+ // argument diagnostic if the code is always run.
+ if (!ForAS && !ForMultilib) {
// Supported only on ARMv6T2 and ARMv7 and above.
- // Cannot be combined with -mno-movt or -mlong-calls
+ // Cannot be combined with -mno-movt.
if (Arg *A = Args.getLastArg(options::OPT_mexecute_only, options::OPT_mno_execute_only)) {
if (A->getOption().matches(options::OPT_mexecute_only)) {
if (getARMSubArchVersionNumber(Triple) < 7 &&
- llvm::ARM::parseArch(Triple.getArchName()) != llvm::ARM::ArchKind::ARMV6T2)
+ llvm::ARM::parseArch(Triple.getArchName()) != llvm::ARM::ArchKind::ARMV6T2 &&
+ llvm::ARM::parseArch(Triple.getArchName()) != llvm::ARM::ArchKind::ARMV6M)
D.Diag(diag::err_target_unsupported_execute_only) << Triple.getArchName();
- else if (Arg *B = Args.getLastArg(options::OPT_mno_movt))
- D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args);
- // Long calls create constant pool entries and have not yet been fixed up
- // to play nicely with execute-only. Hence, they cannot be used in
- // execute-only code for now
- else if (Arg *B = Args.getLastArg(options::OPT_mlong_calls, options::OPT_mno_long_calls)) {
- if (B->getOption().matches(options::OPT_mlong_calls))
- D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args);
- }
+ else if (llvm::ARM::parseArch(Triple.getArchName()) == llvm::ARM::ArchKind::ARMV6M) {
+ if (Arg *PIArg = Args.getLastArg(options::OPT_fropi, options::OPT_frwpi,
+ options::OPT_fpic, options::OPT_fpie,
+ options::OPT_fPIC, options::OPT_fPIE))
+ D.Diag(diag::err_opt_not_valid_with_opt_on_target)
+ << A->getAsString(Args) << PIArg->getAsString(Args) << Triple.getArchName();
+ } else if (Arg *B = Args.getLastArg(options::OPT_mno_movt))
+ D.Diag(diag::err_opt_not_valid_with_opt)
+ << A->getAsString(Args) << B->getAsString(Args);
Features.push_back("+execute-only");
}
}
}
// Kernel code has more strict alignment requirements.
- if (KernelOrKext)
+ if (KernelOrKext) {
Features.push_back("+strict-align");
- else if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
- options::OPT_munaligned_access)) {
+ } else if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
+ options::OPT_munaligned_access)) {
if (A->getOption().matches(options::OPT_munaligned_access)) {
// No v6M core supports unaligned memory access (v6M ARM ARM A3.2).
if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
@@ -763,7 +894,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 +903,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
@@ -823,8 +956,8 @@ fp16_fml_fallthrough:
DisableComdat = true;
continue;
}
- D.Diag(diag::err_invalid_sls_hardening)
- << Scope << A->getAsString(Args);
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getSpelling() << Scope;
break;
}
}
@@ -843,9 +976,15 @@ fp16_fml_fallthrough:
}
}
+ if (Args.getLastArg(options::OPT_mno_bti_at_return_twice))
+ Features.push_back("+no-bti-at-return-twice");
+
+ checkARMFloatABI(D, Args, HasFPRegs);
+
+ return FPUKind;
}
-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);
@@ -881,7 +1020,7 @@ StringRef arm::getARMCPUForMArch(StringRef Arch, const llvm::Triple &Triple) {
// We need to return an empty string here on invalid MArch values as the
// various places that call this function can't cope with a null result.
- return Triple.getARMCPUForArch(MArch);
+ return llvm::ARM::getARMCPUForArch(Triple, MArch);
}
/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting.
@@ -914,7 +1053,8 @@ llvm::ARM::ArchKind arm::getLLVMArchKindForARM(StringRef CPU, StringRef Arch,
if (ArchKind == llvm::ARM::ArchKind::INVALID)
// In case of generic Arch, i.e. "arm",
// extract arch from default cpu of the Triple
- ArchKind = llvm::ARM::parseCPUArch(Triple.getARMCPUForArch(ARMArch));
+ ArchKind =
+ llvm::ARM::parseCPUArch(llvm::ARM::getARMCPUForArch(Triple, ARMArch));
} else {
// FIXME: horrible hack to get around the fact that Cortex-A7 is only an
// armv7k triple if it's actually been specified via "-arch armv7k".
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/ARM.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/ARM.h
index 8e7c10ecd5d6..fa62ac89e3a1 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/ARM.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/ARM.h
@@ -11,9 +11,10 @@
#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
+#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
-#include "llvm/Support/TargetParser.h"
+#include "llvm/TargetParser/ARMTargetParser.h"
+#include "llvm/TargetParser/Triple.h"
#include <string>
#include <vector>
@@ -24,7 +25,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);
@@ -37,7 +38,9 @@ void appendBE8LinkFlag(const llvm::opt::ArgList &Args,
enum class ReadTPMode {
Invalid,
Soft,
- Cp15,
+ TPIDRURW,
+ TPIDRURO,
+ TPIDRPRW,
};
enum class FloatABI {
@@ -53,7 +56,9 @@ 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);
+bool isHardTPSupported(const llvm::Triple &Triple);
+ReadTPMode getReadTPMode(const Driver &D, const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple, bool ForAS);
void setArchNameInTriple(const Driver &D, const llvm::opt::ArgList &Args,
types::ID InputType, llvm::Triple &Triple);
@@ -61,13 +66,15 @@ bool useAAPCSForMachO(const llvm::Triple &T);
void getARMArchCPUFromArgs(const llvm::opt::ArgList &Args,
llvm::StringRef &Arch, llvm::StringRef &CPU,
bool FromAs = false);
-void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs,
- std::vector<llvm::StringRef> &Features, bool ForAS);
+llvm::ARM::FPUKind getARMTargetFeatures(const Driver &D,
+ const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args,
+ std::vector<llvm::StringRef> &Features,
+ bool ForAS, bool ForMultilib = false);
int getARMSubArchVersionNumber(const llvm::Triple &Triple);
bool isARMMProfile(const llvm::Triple &Triple);
bool isARMAProfile(const llvm::Triple &Triple);
+bool isARMBigEndian(const llvm::Triple &Triple, const llvm::opt::ArgList &Args);
} // end namespace arm
} // end namespace tools
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/CSKY.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/CSKY.cpp
new file mode 100644
index 000000000000..e94ea12f46dc
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/CSKY.cpp
@@ -0,0 +1,169 @@
+//===--- CSKY.cpp - CSKY Helpers for Tools --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "CSKY.h"
+#include "ToolChains/CommonArgs.h"
+#include "clang/Basic/CharInfo.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TargetParser/CSKYTargetParser.h"
+#include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/TargetParser.h"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+std::optional<llvm::StringRef>
+csky::getCSKYArchName(const Driver &D, const ArgList &Args,
+ const llvm::Triple &Triple) {
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ llvm::CSKY::ArchKind ArchKind = llvm::CSKY::parseArch(A->getValue());
+
+ if (ArchKind == llvm::CSKY::ArchKind::INVALID) {
+ D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args);
+ return std::nullopt;
+ }
+ return std::optional<llvm::StringRef>(A->getValue());
+ }
+
+ if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) {
+ llvm::CSKY::ArchKind ArchKind = llvm::CSKY::parseCPUArch(A->getValue());
+ if (ArchKind == llvm::CSKY::ArchKind::INVALID) {
+ D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ return std::nullopt;
+ }
+ return std::optional<llvm::StringRef>(llvm::CSKY::getArchName(ArchKind));
+ }
+
+ return std::optional<llvm::StringRef>("ck810");
+}
+
+csky::FloatABI csky::getCSKYFloatABI(const Driver &D, const ArgList &Args) {
+ csky::FloatABI ABI = FloatABI::Soft;
+ if (Arg *A =
+ Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
+ options::OPT_mfloat_abi_EQ)) {
+ if (A->getOption().matches(options::OPT_msoft_float)) {
+ ABI = FloatABI::Soft;
+ } else if (A->getOption().matches(options::OPT_mhard_float)) {
+ ABI = FloatABI::Hard;
+ } else {
+ ABI = llvm::StringSwitch<csky::FloatABI>(A->getValue())
+ .Case("soft", FloatABI::Soft)
+ .Case("softfp", FloatABI::SoftFP)
+ .Case("hard", FloatABI::Hard)
+ .Default(FloatABI::Invalid);
+ if (ABI == FloatABI::Invalid) {
+ D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
+ ABI = FloatABI::Soft;
+ }
+ }
+ }
+
+ return ABI;
+}
+
+// Handle -mfpu=.
+static llvm::CSKY::CSKYFPUKind
+getCSKYFPUFeatures(const Driver &D, const Arg *A, const ArgList &Args,
+ StringRef FPU, std::vector<StringRef> &Features) {
+
+ llvm::CSKY::CSKYFPUKind FPUID =
+ llvm::StringSwitch<llvm::CSKY::CSKYFPUKind>(FPU)
+ .Case("auto", llvm::CSKY::FK_AUTO)
+ .Case("fpv2", llvm::CSKY::FK_FPV2)
+ .Case("fpv2_divd", llvm::CSKY::FK_FPV2_DIVD)
+ .Case("fpv2_sf", llvm::CSKY::FK_FPV2_SF)
+ .Case("fpv3", llvm::CSKY::FK_FPV3)
+ .Case("fpv3_hf", llvm::CSKY::FK_FPV3_HF)
+ .Case("fpv3_hsf", llvm::CSKY::FK_FPV3_HSF)
+ .Case("fpv3_sdf", llvm::CSKY::FK_FPV3_SDF)
+ .Default(llvm::CSKY::FK_INVALID);
+ if (FPUID == llvm::CSKY::FK_INVALID) {
+ D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ return llvm::CSKY::FK_INVALID;
+ }
+
+ auto RemoveTargetFPUFeature =
+ [&Features](ArrayRef<const char *> FPUFeatures) {
+ for (auto FPUFeature : FPUFeatures) {
+ auto it = llvm::find(Features, FPUFeature);
+ if (it != Features.end())
+ Features.erase(it);
+ }
+ };
+
+ RemoveTargetFPUFeature({"+fpuv2_sf", "+fpuv2_df", "+fdivdu", "+fpuv3_hi",
+ "+fpuv3_hf", "+fpuv3_sf", "+fpuv3_df"});
+
+ if (!llvm::CSKY::getFPUFeatures(FPUID, Features)) {
+ D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ return llvm::CSKY::FK_INVALID;
+ }
+
+ return FPUID;
+}
+
+void csky::getCSKYTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args, ArgStringList &CmdArgs,
+ std::vector<llvm::StringRef> &Features) {
+ llvm::StringRef archName;
+ llvm::StringRef cpuName;
+ llvm::CSKY::ArchKind ArchKind = llvm::CSKY::ArchKind::INVALID;
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ ArchKind = llvm::CSKY::parseArch(A->getValue());
+ if (ArchKind == llvm::CSKY::ArchKind::INVALID) {
+ D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args);
+ return;
+ }
+ archName = A->getValue();
+ }
+
+ if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) {
+ llvm::CSKY::ArchKind Kind = llvm::CSKY::parseCPUArch(A->getValue());
+ if (Kind == llvm::CSKY::ArchKind::INVALID) {
+ D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ return;
+ }
+ if (!archName.empty() && Kind != ArchKind) {
+ D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ return;
+ }
+ cpuName = A->getValue();
+ if (archName.empty())
+ archName = llvm::CSKY::getArchName(Kind);
+ }
+
+ if (archName.empty() && cpuName.empty()) {
+ archName = "ck810";
+ cpuName = "ck810";
+ } else if (!archName.empty() && cpuName.empty()) {
+ cpuName = archName;
+ }
+
+ csky::FloatABI FloatABI = csky::getCSKYFloatABI(D, Args);
+
+ if (FloatABI == csky::FloatABI::Hard) {
+ Features.push_back("+hard-float-abi");
+ Features.push_back("+hard-float");
+ } else if (FloatABI == csky::FloatABI::SoftFP) {
+ Features.push_back("+hard-float");
+ }
+
+ uint64_t Extension = llvm::CSKY::getDefaultExtensions(cpuName);
+ llvm::CSKY::getExtensionFeatures(Extension, Features);
+
+ if (const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ))
+ getCSKYFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features);
+}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/CSKY.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/CSKY.h
new file mode 100644
index 000000000000..f3730d2cf4a1
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/CSKY.h
@@ -0,0 +1,47 @@
+//===--- CSKY.h - CSKY-specific Tool Helpers ------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_CSKY_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_CSKY_H
+
+#include "clang/Driver/Driver.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace driver {
+namespace tools {
+namespace csky {
+
+enum class FloatABI {
+ Invalid,
+ Soft,
+ SoftFP,
+ Hard,
+};
+
+FloatABI getCSKYFloatABI(const Driver &D, const llvm::opt::ArgList &Args);
+
+void getCSKYTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs,
+ std::vector<llvm::StringRef> &Features);
+
+std::optional<llvm::StringRef> getCSKYArchName(const Driver &D,
+ const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple);
+
+} // end namespace csky
+} // namespace tools
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_CSKY_H
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
new file mode 100644
index 000000000000..31153a67ad28
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
@@ -0,0 +1,232 @@
+//===--- LoongArch.cpp - LoongArch Helpers for Tools ------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "LoongArch.h"
+#include "ToolChains/CommonArgs.h"
+#include "clang/Basic/DiagnosticDriver.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/LoongArchTargetParser.h"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+StringRef loongarch::getLoongArchABI(const Driver &D, const ArgList &Args,
+ const llvm::Triple &Triple) {
+ assert((Triple.getArch() == llvm::Triple::loongarch32 ||
+ Triple.getArch() == llvm::Triple::loongarch64) &&
+ "Unexpected triple");
+ bool IsLA32 = Triple.getArch() == llvm::Triple::loongarch32;
+
+ // Record -mabi value for later use.
+ const Arg *MABIArg = Args.getLastArg(options::OPT_mabi_EQ);
+ StringRef MABIValue;
+ if (MABIArg) {
+ MABIValue = MABIArg->getValue();
+ }
+
+ // Parse -mfpu value for later use.
+ const Arg *MFPUArg = Args.getLastArg(options::OPT_mfpu_EQ);
+ int FPU = -1;
+ if (MFPUArg) {
+ StringRef V = MFPUArg->getValue();
+ if (V == "64")
+ FPU = 64;
+ else if (V == "32")
+ FPU = 32;
+ else if (V == "0" || V == "none")
+ FPU = 0;
+ else
+ D.Diag(diag::err_drv_loongarch_invalid_mfpu_EQ) << V;
+ }
+
+ // Check -m*-float firstly since they have highest priority.
+ if (const Arg *A = Args.getLastArg(options::OPT_mdouble_float,
+ options::OPT_msingle_float,
+ options::OPT_msoft_float)) {
+ StringRef ImpliedABI;
+ int ImpliedFPU = -1;
+ if (A->getOption().matches(options::OPT_mdouble_float)) {
+ ImpliedABI = IsLA32 ? "ilp32d" : "lp64d";
+ ImpliedFPU = 64;
+ }
+ if (A->getOption().matches(options::OPT_msingle_float)) {
+ ImpliedABI = IsLA32 ? "ilp32f" : "lp64f";
+ ImpliedFPU = 32;
+ }
+ if (A->getOption().matches(options::OPT_msoft_float)) {
+ ImpliedABI = IsLA32 ? "ilp32s" : "lp64s";
+ ImpliedFPU = 0;
+ }
+
+ // Check `-mabi=` and `-mfpu=` settings and report if they conflict with
+ // the higher-priority settings implied by -m*-float.
+ //
+ // ImpliedABI and ImpliedFPU are guaranteed to have valid values because
+ // one of the match arms must match if execution can arrive here at all.
+ if (!MABIValue.empty() && ImpliedABI != MABIValue)
+ D.Diag(diag::warn_drv_loongarch_conflicting_implied_val)
+ << MABIArg->getAsString(Args) << A->getAsString(Args) << ImpliedABI;
+
+ if (FPU != -1 && ImpliedFPU != FPU)
+ D.Diag(diag::warn_drv_loongarch_conflicting_implied_val)
+ << MFPUArg->getAsString(Args) << A->getAsString(Args) << ImpliedFPU;
+
+ return ImpliedABI;
+ }
+
+ // If `-mabi=` is specified, use it.
+ if (!MABIValue.empty())
+ return MABIValue;
+
+ // Select abi based on -mfpu=xx.
+ switch (FPU) {
+ case 64:
+ return IsLA32 ? "ilp32d" : "lp64d";
+ case 32:
+ return IsLA32 ? "ilp32f" : "lp64f";
+ case 0:
+ return IsLA32 ? "ilp32s" : "lp64s";
+ }
+
+ // Choose a default based on the triple.
+ // Honor the explicit ABI modifier suffix in triple's environment part if
+ // present, falling back to {ILP32,LP64}D otherwise.
+ switch (Triple.getEnvironment()) {
+ case llvm::Triple::GNUSF:
+ return IsLA32 ? "ilp32s" : "lp64s";
+ case llvm::Triple::GNUF32:
+ return IsLA32 ? "ilp32f" : "lp64f";
+ case llvm::Triple::GNUF64:
+ // This was originally permitted (and indeed the canonical way) to
+ // represent the {ILP32,LP64}D ABIs, but in Feb 2023 Loongson decided to
+ // drop the explicit suffix in favor of unmarked `-gnu` for the
+ // "general-purpose" ABIs, among other non-technical reasons.
+ //
+ // The spec change did not mention whether existing usages of "gnuf64"
+ // shall remain valid or not, so we are going to continue recognizing it
+ // for some time, until it is clear that everyone else has migrated away
+ // from it.
+ [[fallthrough]];
+ case llvm::Triple::GNU:
+ default:
+ return IsLA32 ? "ilp32d" : "lp64d";
+ }
+}
+
+void loongarch::getLoongArchTargetFeatures(const Driver &D,
+ const llvm::Triple &Triple,
+ const ArgList &Args,
+ std::vector<StringRef> &Features) {
+ std::string ArchName;
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
+ ArchName = A->getValue();
+ ArchName = postProcessTargetCPUString(ArchName, Triple);
+ llvm::LoongArch::getArchFeatures(ArchName, Features);
+
+ // Select floating-point features determined by -mdouble-float,
+ // -msingle-float, -msoft-float and -mfpu.
+ // Note: -m*-float wins any other options.
+ if (const Arg *A = Args.getLastArg(options::OPT_mdouble_float,
+ options::OPT_msingle_float,
+ options::OPT_msoft_float)) {
+ if (A->getOption().matches(options::OPT_mdouble_float)) {
+ Features.push_back("+f");
+ Features.push_back("+d");
+ } else if (A->getOption().matches(options::OPT_msingle_float)) {
+ Features.push_back("+f");
+ Features.push_back("-d");
+ } else /*Soft-float*/ {
+ Features.push_back("-f");
+ Features.push_back("-d");
+ }
+ } else if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) {
+ StringRef FPU = A->getValue();
+ if (FPU == "64") {
+ Features.push_back("+f");
+ Features.push_back("+d");
+ } else if (FPU == "32") {
+ Features.push_back("+f");
+ Features.push_back("-d");
+ } else if (FPU == "0" || FPU == "none") {
+ Features.push_back("-f");
+ Features.push_back("-d");
+ } else {
+ D.Diag(diag::err_drv_loongarch_invalid_mfpu_EQ) << FPU;
+ }
+ }
+
+ // Select the `ual` feature determined by -m[no-]unaligned-access
+ // or the alias -m[no-]strict-align.
+ AddTargetFeature(Args, Features, options::OPT_munaligned_access,
+ options::OPT_mno_unaligned_access, "ual");
+
+ // Accept but warn about these TargetSpecific options.
+ if (Arg *A = Args.getLastArgNoClaim(options::OPT_mabi_EQ))
+ A->ignoreTargetSpecific();
+ if (Arg *A = Args.getLastArgNoClaim(options::OPT_mfpu_EQ))
+ A->ignoreTargetSpecific();
+
+ // Select lsx feature determined by -m[no-]lsx.
+ if (const Arg *A = Args.getLastArg(options::OPT_mlsx, options::OPT_mno_lsx)) {
+ // LSX depends on 64-bit FPU.
+ // -m*-float and -mfpu=none/0/32 conflict with -mlsx.
+ if (A->getOption().matches(options::OPT_mlsx)) {
+ if (llvm::find(Features, "-d") != Features.end())
+ D.Diag(diag::err_drv_loongarch_wrong_fpu_width_for_lsx);
+ else /*-mlsx*/
+ Features.push_back("+lsx");
+ } else /*-mno-lsx*/ {
+ Features.push_back("-lsx");
+ }
+ }
+
+ // Select lasx feature determined by -m[no-]lasx.
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_mlasx, options::OPT_mno_lasx)) {
+ // LASX depends on 64-bit FPU and LSX.
+ // -mno-lsx conflicts with -mlasx.
+ if (A->getOption().matches(options::OPT_mlasx)) {
+ if (llvm::find(Features, "-d") != Features.end())
+ D.Diag(diag::err_drv_loongarch_wrong_fpu_width_for_lasx);
+ else if (llvm::find(Features, "-lsx") != Features.end())
+ D.Diag(diag::err_drv_loongarch_invalid_simd_option_combination);
+ else { /*-mlasx*/
+ Features.push_back("+lsx");
+ Features.push_back("+lasx");
+ }
+ } else /*-mno-lasx*/
+ Features.push_back("-lasx");
+ }
+}
+
+std::string loongarch::postProcessTargetCPUString(const std::string &CPU,
+ const llvm::Triple &Triple) {
+ std::string CPUString = CPU;
+ if (CPUString == "native") {
+ CPUString = llvm::sys::getHostCPUName();
+ if (CPUString == "generic")
+ CPUString = llvm::LoongArch::getDefaultArch(Triple.isLoongArch64());
+ }
+ if (CPUString.empty())
+ CPUString = llvm::LoongArch::getDefaultArch(Triple.isLoongArch64());
+ return CPUString;
+}
+
+std::string loongarch::getLoongArchTargetCPU(const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple) {
+ std::string CPU;
+ // If we have -march, use that.
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
+ CPU = A->getValue();
+ return postProcessTargetCPUString(CPU, Triple);
+}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/LoongArch.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/LoongArch.h
new file mode 100644
index 000000000000..d8280cd836f8
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/LoongArch.h
@@ -0,0 +1,37 @@
+//===--- LoongArch.h - LoongArch-specific Tool Helpers ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_LOONGARCH_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_LOONGARCH_H
+
+#include "clang/Driver/Driver.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/Option.h"
+
+namespace clang {
+namespace driver {
+namespace tools {
+namespace loongarch {
+void getLoongArchTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args,
+ std::vector<llvm::StringRef> &Features);
+
+StringRef getLoongArchABI(const Driver &D, const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple);
+
+std::string postProcessTargetCPUString(const std::string &CPU,
+ const llvm::Triple &Triple);
+
+std::string getLoongArchTargetCPU(const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple);
+} // end namespace loongarch
+} // end namespace tools
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_LOONGARCH_H
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/M68k.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/M68k.cpp
index 119e24cedbab..963f7a187d63 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/M68k.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/M68k.cpp
@@ -14,8 +14,8 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/ArgList.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/Regex.h"
+#include "llvm/TargetParser/Host.h"
#include <sstream>
using namespace clang::driver;
@@ -65,13 +65,35 @@ std::string m68k::getM68kTargetCPU(const ArgList &Args) {
return "";
}
+static void addFloatABIFeatures(const llvm::opt::ArgList &Args,
+ std::vector<llvm::StringRef> &Features) {
+ Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
+ options::OPT_m68881);
+ // Opt out FPU even for newer CPUs.
+ if (A && A->getOption().matches(options::OPT_msoft_float)) {
+ Features.push_back("-isa-68881");
+ Features.push_back("-isa-68882");
+ return;
+ }
+
+ std::string CPU = m68k::getM68kTargetCPU(Args);
+ // Only enable M68881 for CPU < 68020 if the related flags are present.
+ if ((A && (CPU == "M68000" || CPU == "M68010")) ||
+ // Otherwise, by default we assume newer CPUs have M68881/2.
+ CPU == "M68020")
+ Features.push_back("+isa-68881");
+ else if (CPU == "M68030" || CPU == "M68040" || CPU == "M68060")
+ // Note that although CPU >= M68040 imply M68882, we still add `isa-68882`
+ // anyway so that it's easier to add or not add the corresponding macro
+ // definitions later, in case we want to disable 68881/2 in newer CPUs
+ // (with -msoft-float, for instance).
+ Features.push_back("+isa-68882");
+}
+
void m68k::getM68kTargetFeatures(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args,
std::vector<StringRef> &Features) {
-
- m68k::FloatABI FloatABI = m68k::getM68kFloatABI(D, Args);
- if (FloatABI == m68k::FloatABI::Soft)
- Features.push_back("-hard-float");
+ addFloatABIFeatures(Args, Features);
// Handle '-ffixed-<register>' flags
if (Args.hasArg(options::OPT_ffixed_a0))
@@ -105,21 +127,3 @@ void m68k::getM68kTargetFeatures(const Driver &D, const llvm::Triple &Triple,
if (Args.hasArg(options::OPT_ffixed_d7))
Features.push_back("+reserve-d7");
}
-
-m68k::FloatABI m68k::getM68kFloatABI(const Driver &D, const ArgList &Args) {
- m68k::FloatABI ABI = m68k::FloatABI::Invalid;
- if (Arg *A =
- Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float)) {
-
- if (A->getOption().matches(options::OPT_msoft_float))
- ABI = m68k::FloatABI::Soft;
- else if (A->getOption().matches(options::OPT_mhard_float))
- ABI = m68k::FloatABI::Hard;
- }
-
- // If unspecified, choose the default based on the platform.
- if (ABI == m68k::FloatABI::Invalid)
- ABI = m68k::FloatABI::Hard;
-
- return ABI;
-}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/M68k.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/M68k.h
index 41d53efb940b..051e7e1af103 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/M68k.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/M68k.h
@@ -20,14 +20,6 @@ namespace driver {
namespace tools {
namespace m68k {
-enum class FloatABI {
- Invalid,
- Soft,
- Hard,
-};
-
-FloatABI getM68kFloatABI(const Driver &D, const llvm::opt::ArgList &Args);
-
std::string getM68kTargetCPU(const llvm::opt::ArgList &Args);
void getM68kTargetFeatures(const Driver &D, const llvm::Triple &Triple,
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/Mips.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/Mips.cpp
index 5a509dbb2bd3..fe9d112b8800 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/Mips.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/Mips.cpp
@@ -39,12 +39,6 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
DefMips64CPU = "mips64r6";
}
- // MIPS64r6 is the default for Android MIPS64 (mips64el-linux-android).
- if (Triple.isAndroid()) {
- DefMips32CPU = "mips32";
- DefMips64CPU = "mips64r6";
- }
-
// MIPS3 is the default for mips64*-unknown-openbsd.
if (Triple.isOSOpenBSD())
DefMips64CPU = "mips3";
@@ -227,6 +221,7 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
bool IsN64 = ABIName == "64";
bool IsPIC = false;
bool NonPIC = false;
+ bool HasNaN2008Opt = false;
Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
options::OPT_fpic, options::OPT_fno_pic,
@@ -291,9 +286,10 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
StringRef Val = StringRef(A->getValue());
if (Val == "2008") {
- if (mips::getIEEE754Standard(CPUName) & mips::Std2008)
+ if (mips::getIEEE754Standard(CPUName) & mips::Std2008) {
Features.push_back("+nan2008");
- else {
+ HasNaN2008Opt = true;
+ } else {
Features.push_back("-nan2008");
D.Diag(diag::warn_target_unsupported_nan2008) << CPUName;
}
@@ -306,7 +302,7 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
}
} else
D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << Val;
+ << A->getSpelling() << Val;
}
if (Arg *A = Args.getLastArg(options::OPT_mabs_EQ)) {
@@ -327,8 +323,10 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
}
} else {
D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << Val;
+ << A->getSpelling() << Val;
}
+ } else if (HasNaN2008Opt) {
+ Features.push_back("+abs2008");
}
AddTargetFeature(Args, Features, options::OPT_msingle_float,
@@ -441,7 +439,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 +448,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);
}
@@ -466,11 +465,6 @@ bool mips::isFP64ADefault(const llvm::Triple &Triple, StringRef CPUName) {
bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
StringRef ABIName, mips::FloatABI FloatABI) {
- if (Triple.getVendor() != llvm::Triple::ImaginationTechnologies &&
- Triple.getVendor() != llvm::Triple::MipsTechnologies &&
- !Triple.isAndroid())
- return false;
-
if (ABIName != "32")
return false;
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/Mips.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/Mips.h
index 074012f40fe5..62211c711420 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/Mips.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/Mips.h
@@ -11,8 +11,8 @@
#include "clang/Driver/Driver.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/Option/Option.h"
+#include "llvm/TargetParser/Triple.h"
#include <string>
#include <vector>
@@ -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/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/PPC.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/PPC.cpp
index bcaecf4b2d98..ab24d14992cd 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/PPC.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/PPC.cpp
@@ -13,81 +13,83 @@
#include "clang/Driver/Options.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/ArgList.h"
-#include "llvm/Support/Host.h"
+#include "llvm/TargetParser/Host.h"
using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;
-/// getPPCTargetCPU - Get the (LLVM) name of the PowerPC cpu we are targeting.
-std::string ppc::getPPCTargetCPU(const ArgList &Args) {
- if (Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) {
- StringRef CPUName = A->getValue();
-
- if (CPUName == "native") {
- std::string CPU = std::string(llvm::sys::getHostCPUName());
- if (!CPU.empty() && CPU != "generic")
- return CPU;
- else
- return "";
- }
+static std::string getPPCGenericTargetCPU(const llvm::Triple &T) {
+ // LLVM may default to generating code for the native CPU,
+ // but, like gcc, we default to a more generic option for
+ // each architecture. (except on AIX)
+ if (T.isOSAIX())
+ return "pwr7";
+ else if (T.getArch() == llvm::Triple::ppc64le)
+ return "ppc64le";
+ else if (T.getArch() == llvm::Triple::ppc64)
+ return "ppc64";
+ else
+ return "ppc";
+}
- return llvm::StringSwitch<const char *>(CPUName)
- .Case("common", "generic")
- .Case("440", "440")
- .Case("440fp", "440")
- .Case("450", "450")
- .Case("601", "601")
- .Case("602", "602")
- .Case("603", "603")
- .Case("603e", "603e")
- .Case("603ev", "603ev")
- .Case("604", "604")
- .Case("604e", "604e")
- .Case("620", "620")
- .Case("630", "pwr3")
- .Case("G3", "g3")
- .Case("7400", "7400")
- .Case("G4", "g4")
- .Case("7450", "7450")
- .Case("G4+", "g4+")
- .Case("750", "750")
- .Case("8548", "e500")
- .Case("970", "970")
- .Case("G5", "g5")
- .Case("a2", "a2")
- .Case("e500", "e500")
- .Case("e500mc", "e500mc")
- .Case("e5500", "e5500")
- .Case("power3", "pwr3")
- .Case("power4", "pwr4")
- .Case("power5", "pwr5")
- .Case("power5x", "pwr5x")
- .Case("power6", "pwr6")
- .Case("power6x", "pwr6x")
- .Case("power7", "pwr7")
- .Case("power8", "pwr8")
- .Case("power9", "pwr9")
- .Case("power10", "pwr10")
- .Case("future", "future")
- .Case("pwr3", "pwr3")
- .Case("pwr4", "pwr4")
- .Case("pwr5", "pwr5")
- .Case("pwr5x", "pwr5x")
- .Case("pwr6", "pwr6")
- .Case("pwr6x", "pwr6x")
- .Case("pwr7", "pwr7")
- .Case("pwr8", "pwr8")
- .Case("pwr9", "pwr9")
- .Case("pwr10", "pwr10")
- .Case("powerpc", "ppc")
- .Case("powerpc64", "ppc64")
- .Case("powerpc64le", "ppc64le")
- .Default("");
+static std::string normalizeCPUName(StringRef CPUName, const llvm::Triple &T) {
+ // Clang/LLVM does not actually support code generation
+ // for the 405 CPU. However, there are uses of this CPU ID
+ // in projects that previously used GCC and rely on Clang
+ // accepting it. Clang has always ignored it and passed the
+ // generic CPU ID to the back end.
+ if (CPUName == "generic" || CPUName == "405")
+ return getPPCGenericTargetCPU(T);
+
+ if (CPUName == "native") {
+ std::string CPU = std::string(llvm::sys::getHostCPUName());
+ if (!CPU.empty() && CPU != "generic")
+ return CPU;
+ else
+ return getPPCGenericTargetCPU(T);
}
- return "";
+ return llvm::StringSwitch<const char *>(CPUName)
+ .Case("common", "generic")
+ .Case("440fp", "440")
+ .Case("630", "pwr3")
+ .Case("G3", "g3")
+ .Case("G4", "g4")
+ .Case("G4+", "g4+")
+ .Case("8548", "e500")
+ .Case("G5", "g5")
+ .Case("power3", "pwr3")
+ .Case("power4", "pwr4")
+ .Case("power5", "pwr5")
+ .Case("power5x", "pwr5x")
+ .Case("power6", "pwr6")
+ .Case("power6x", "pwr6x")
+ .Case("power7", "pwr7")
+ .Case("power8", "pwr8")
+ .Case("power9", "pwr9")
+ .Case("power10", "pwr10")
+ .Case("future", "future")
+ .Case("powerpc", "ppc")
+ .Case("powerpc64", "ppc64")
+ .Case("powerpc64le", "ppc64le")
+ .Default(CPUName.data());
+}
+
+/// Get the (LLVM) name of the PowerPC cpu we are tuning for.
+std::string ppc::getPPCTuneCPU(const ArgList &Args, const llvm::Triple &T) {
+ if (Arg *A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ))
+ return normalizeCPUName(A->getValue(), T);
+ return getPPCGenericTargetCPU(T);
+}
+
+/// Get the (LLVM) name of the PowerPC cpu we are targeting.
+std::string ppc::getPPCTargetCPU(const Driver &D, const ArgList &Args,
+ const llvm::Triple &T) {
+ if (Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ))
+ return normalizeCPUName(A->getValue(), T);
+ return getPPCGenericTargetCPU(T);
}
const char *ppc::getPPCAsmModeForCPU(StringRef Name) {
@@ -110,7 +112,8 @@ void ppc::getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,
if (Triple.getSubArch() == llvm::Triple::PPCSubArch_spe)
Features.push_back("+spe");
- handleTargetFeaturesGroup(Args, Features, options::OPT_m_ppc_Features_Group);
+ handleTargetFeaturesGroup(D, Triple, Args, Features,
+ options::OPT_m_ppc_Features_Group);
ppc::FloatABI FloatABI = ppc::getPPCFloatABI(D, Args);
if (FloatABI == ppc::FloatABI::Soft)
@@ -125,8 +128,7 @@ ppc::ReadGOTPtrMode ppc::getPPCReadGOTPtrMode(const Driver &D, const llvm::Tripl
const ArgList &Args) {
if (Args.getLastArg(options::OPT_msecure_plt))
return ppc::ReadGOTPtrMode::SecurePlt;
- if ((Triple.isOSFreeBSD() && Triple.getOSMajorVersion() >= 13) ||
- Triple.isOSNetBSD() || Triple.isOSOpenBSD() || Triple.isMusl())
+ if (Triple.isPPC32SecurePlt())
return ppc::ReadGOTPtrMode::SecurePlt;
else
return ppc::ReadGOTPtrMode::Bss;
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/PPC.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/PPC.h
index e1c943955e81..ec5b3c8140b6 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/PPC.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/PPC.h
@@ -35,7 +35,10 @@ enum class ReadGOTPtrMode {
FloatABI getPPCFloatABI(const Driver &D, const llvm::opt::ArgList &Args);
-std::string getPPCTargetCPU(const llvm::opt::ArgList &Args);
+std::string getPPCTargetCPU(const Driver &D, const llvm::opt::ArgList &Args,
+ const llvm::Triple &T);
+std::string getPPCTuneCPU(const llvm::opt::ArgList &Args,
+ const llvm::Triple &T);
const char *getPPCAsmModeForCPU(StringRef Name);
ReadGOTPtrMode getPPCReadGOTPtrMode(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
index 2c2404acc54d..47b29e1577c2 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -1,4 +1,4 @@
-//===--- RISCV.cpp - RISCV Helpers for Tools --------------------*- C++ -*-===//
+//===--- RISCV.cpp - RISC-V Helpers for Tools -------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -7,476 +7,69 @@
//===----------------------------------------------------------------------===//
#include "RISCV.h"
+#include "../Clang.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/Support/TargetParser.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/RISCVISAInfo.h"
#include "llvm/Support/raw_ostream.h"
-#include "ToolChains/CommonArgs.h"
+#include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/RISCVTargetParser.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");
+ 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();
+ });
- // 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);
- }
-
- 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;
- }
+ for (const std::string &Str : (*ISAInfo)->toFeatures(/*AddAllExtension=*/true,
+ /*IgnoreUnknown=*/false))
+ Features.push_back(Args.MakeArgString(Str));
- // 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);
+ if (EnableExperimentalExtensions)
+ Features.push_back(Args.MakeArgString("+experimental"));
return true;
}
// Get features except standard extension feature
-static void getRISCFeaturesFromMcpu(const Driver &D, const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args,
- const llvm::opt::Arg *A, StringRef Mcpu,
+static void getRISCFeaturesFromMcpu(const Driver &D, const Arg *A,
+ const llvm::Triple &Triple,
+ StringRef Mcpu,
std::vector<StringRef> &Features) {
- bool Is64Bit = (Triple.getArch() == llvm::Triple::riscv64);
- llvm::RISCV::CPUKind CPUKind = llvm::RISCV::parseCPUKind(Mcpu);
- if (!llvm::RISCV::checkCPUKind(CPUKind, Is64Bit) ||
- !llvm::RISCV::getCPUFeaturesExceptStdExt(CPUKind, Features)) {
- D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ bool Is64Bit = Triple.isRISCV64();
+ if (!llvm::RISCV::parseCPU(Mcpu, Is64Bit)) {
+ // Try inverting Is64Bit in case the CPU is valid, but for the wrong target.
+ if (llvm::RISCV::parseCPU(Mcpu, !Is64Bit))
+ D.Diag(clang::diag::err_drv_invalid_riscv_cpu_name_for_target)
+ << Mcpu << Is64Bit;
+ else
+ D.Diag(clang::diag::err_drv_unsupported_option_argument)
+ << A->getSpelling() << Mcpu;
}
+
+ if (llvm::RISCV::hasFastUnalignedAccess(Mcpu))
+ Features.push_back("+fast-unaligned-access");
}
void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
@@ -489,8 +82,13 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
// If users give march and mcpu, get std extension feature from MArch
// and other features (ex. mirco architecture feature) from mcpu
- if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
- getRISCFeaturesFromMcpu(D, Triple, Args, A, A->getValue(), Features);
+ if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
+ StringRef CPU = A->getValue();
+ if (CPU == "native")
+ CPU = llvm::sys::getHostCPUName();
+
+ getRISCFeaturesFromMcpu(D, A, Triple, CPU, Features);
+ }
// Handle features corresponding to "-ffixed-X" options
if (Args.hasArg(options::OPT_ffixed_x1))
@@ -558,27 +156,30 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
// FreeBSD local, because ld.lld doesn't support relaxations
// -mno-relax is default, unless -mrelax is specified.
- if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, false))
+ if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, false)) {
Features.push_back("+relax");
- else
+ // -gsplit-dwarf -mrelax requires DW_AT_high_pc/DW_AT_ranges/... indexing
+ // into .debug_addr, which is currently not implemented.
+ Arg *A;
+ if (getDebugFissionKind(D, Args, A) != DwarfFissionKind::None)
+ D.Diag(clang::diag::err_drv_riscv_unsupported_with_linker_relaxation)
+ << A->getAsString(Args);
+ } else {
Features.push_back("-relax");
+ }
- // GCC Compatibility: -mno-save-restore is default, unless -msave-restore is
- // specified.
- if (Args.hasFlag(options::OPT_msave_restore, options::OPT_mno_save_restore, false))
- Features.push_back("+save-restore");
- else
- Features.push_back("-save-restore");
+ // -mno-unaligned-access is default, unless -munaligned-access is specified.
+ AddTargetFeature(Args, Features, options::OPT_munaligned_access,
+ options::OPT_mno_unaligned_access, "fast-unaligned-access");
// Now add any that the user explicitly requested on the command line,
// which may override the defaults.
- handleTargetFeaturesGroup(Args, Features, options::OPT_m_riscv_Features_Group);
+ handleTargetFeaturesGroup(D, Triple, Args, Features,
+ options::OPT_m_riscv_Features_Group);
}
StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) {
- assert((Triple.getArch() == llvm::Triple::riscv32 ||
- Triple.getArch() == llvm::Triple::riscv64) &&
- "Unexpected triple");
+ assert(Triple.isRISCV() && "Unexpected triple");
// GCC's logic around choosing a default `-mabi=` is complex. If GCC is not
// configured using `--with-abi=`, then the logic for the default choice is
@@ -610,33 +211,22 @@ StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) {
// rv32e -> ilp32e
// rv32* -> ilp32
// rv64g | rv64*d -> lp64d
+ // rv64e -> lp64e
// 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
- 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
- return "lp64";
- }
+ auto ParseResult = llvm::RISCVISAInfo::parseArchString(
+ Arch, /* EnableExperimentalExtension */ true);
+ // Ignore parsing error, just go 3rd step.
+ if (!llvm::errorToBool(ParseResult.takeError()))
+ return (*ParseResult)->computeDefaultABI();
// 3. Choose a default based on the triple
//
// We deviate from GCC's defaults here:
// - On `riscv{XLEN}-unknown-elf` we use the integer calling convention only.
// - On all other OSs we use the double floating point calling convention.
- if (Triple.getArch() == llvm::Triple::riscv32) {
+ if (Triple.isRISCV32()) {
if (Triple.getOS() == llvm::Triple::UnknownOS)
return "ilp32";
else
@@ -651,9 +241,7 @@ StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) {
StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args,
const llvm::Triple &Triple) {
- assert((Triple.getArch() == llvm::Triple::riscv32 ||
- Triple.getArch() == llvm::Triple::riscv64) &&
- "Unexpected triple");
+ assert(Triple.isRISCV() && "Unexpected triple");
// GCC's logic around choosing a default `-march=` is complex. If GCC is not
// configured using `--with-arch=`, then the logic for the default choice is
@@ -687,7 +275,10 @@ StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args,
// 2. Get march (isa string) based on `-mcpu=`
if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
- StringRef MArch = llvm::RISCV::getMArchFromMcpu(A->getValue());
+ StringRef CPU = A->getValue();
+ if (CPU == "native")
+ CPU = llvm::sys::getHostCPUName();
+ StringRef MArch = llvm::RISCV::getMArchFromMcpu(CPU);
// Bypass if target cpu's default march is empty.
if (MArch != "")
return MArch;
@@ -696,6 +287,7 @@ StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args,
// 3. Choose a default based on `-mabi=`
//
// ilp32e -> rv32e
+ // lp64e -> rv64e
// ilp32 | ilp32f | ilp32d -> rv32imafdc
// lp64 | lp64f | lp64d -> rv64imafdc
if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
@@ -703,10 +295,16 @@ StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args,
if (MABI.equals_insensitive("ilp32e"))
return "rv32e";
- else if (MABI.startswith_insensitive("ilp32"))
+ else if (MABI.equals_insensitive("lp64e"))
+ return "rv64e";
+ else if (MABI.starts_with_insensitive("ilp32"))
return "rv32imafdc";
- else if (MABI.startswith_insensitive("lp64"))
+ else if (MABI.starts_with_insensitive("lp64")) {
+ if (Triple.isAndroid())
+ return "rv64imafdcv_zba_zbb_zbs";
+
return "rv64imafdc";
+ }
}
// 4. Choose a default based on the triple
@@ -714,7 +312,7 @@ StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args,
// We deviate from GCC's defaults here:
// - On `riscv{XLEN}-unknown-elf` we default to `rv{XLEN}imac`
// - On all other OSs we use `rv{XLEN}imafdc` (equivalent to `rv{XLEN}gc`)
- if (Triple.getArch() == llvm::Triple::riscv32) {
+ if (Triple.isRISCV32()) {
if (Triple.getOS() == llvm::Triple::UnknownOS)
return "rv32imac";
else
@@ -722,7 +320,26 @@ StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args,
} else {
if (Triple.getOS() == llvm::Triple::UnknownOS)
return "rv64imac";
+ else if (Triple.isAndroid())
+ return "rv64imafdcv_zba_zbb_zbs";
else
return "rv64imafdc";
}
}
+
+std::string riscv::getRISCVTargetCPU(const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple) {
+ std::string CPU;
+ // If we have -mcpu, use that.
+ if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
+ CPU = A->getValue();
+
+ // Handle CPU name is 'native'.
+ if (CPU == "native")
+ CPU = llvm::sys::getHostCPUName();
+
+ if (!CPU.empty())
+ return CPU;
+
+ return Triple.isRISCV64() ? "generic-rv64" : "generic-rv32";
+}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.h
index d4a519cdab34..fcaf9d57ad13 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.h
@@ -1,4 +1,4 @@
-//===--- RISCV.h - RISCV-specific Tool Helpers ------------------*- C++ -*-===//
+//===--- RISCV.h - RISC-V-specific Tool Helpers -----------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -26,6 +26,8 @@ StringRef getRISCVABI(const llvm::opt::ArgList &Args,
const llvm::Triple &Triple);
StringRef getRISCVArch(const llvm::opt::ArgList &Args,
const llvm::Triple &Triple);
+std::string getRISCVTargetCPU(const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple);
} // end namespace riscv
} // namespace tools
} // end namespace driver
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/Sparc.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/Sparc.cpp
index 70ba8eb2a7d0..ae1a4ba78826 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/Sparc.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/Sparc.cpp
@@ -12,6 +12,7 @@
#include "clang/Driver/Options.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/TargetParser/Host.h"
using namespace clang::driver;
using namespace clang::driver::tools;
@@ -62,10 +63,6 @@ const char *sparc::getSparcAsmModeForCPU(StringRef Name,
.Case("ma2480", "-Aleon")
.Case("ma2485", "-Aleon")
.Case("ma2x8x", "-Aleon")
- .Case("myriad2", "-Aleon")
- .Case("myriad2.1", "-Aleon")
- .Case("myriad2.2", "-Aleon")
- .Case("myriad2.3", "-Aleon")
.Case("leon2", "-Av8")
.Case("at697e", "-Av8")
.Case("at697f", "-Av8")
@@ -81,12 +78,14 @@ const char *sparc::getSparcAsmModeForCPU(StringRef Name,
sparc::FloatABI sparc::getSparcFloatABI(const Driver &D,
const ArgList &Args) {
sparc::FloatABI ABI = sparc::FloatABI::Invalid;
- if (Arg *A = Args.getLastArg(clang::driver::options::OPT_msoft_float,
- options::OPT_mhard_float,
+ if (Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mno_fpu,
+ options::OPT_mhard_float, options::OPT_mfpu,
options::OPT_mfloat_abi_EQ)) {
- if (A->getOption().matches(clang::driver::options::OPT_msoft_float))
+ if (A->getOption().matches(options::OPT_msoft_float) ||
+ A->getOption().matches(options::OPT_mno_fpu))
ABI = sparc::FloatABI::Soft;
- else if (A->getOption().matches(options::OPT_mhard_float))
+ else if (A->getOption().matches(options::OPT_mhard_float) ||
+ A->getOption().matches(options::OPT_mfpu))
ABI = sparc::FloatABI::Hard;
else {
ABI = llvm::StringSwitch<sparc::FloatABI>(A->getValue())
@@ -113,9 +112,151 @@ sparc::FloatABI sparc::getSparcFloatABI(const Driver &D,
return ABI;
}
+std::string sparc::getSparcTargetCPU(const Driver &D, const ArgList &Args,
+ const llvm::Triple &Triple) {
+ if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) {
+ StringRef CPUName = A->getValue();
+ if (CPUName == "native") {
+ std::string CPU = std::string(llvm::sys::getHostCPUName());
+ if (!CPU.empty() && CPU != "generic")
+ return CPU;
+ return "";
+ }
+ return std::string(CPUName);
+ }
+
+ if (Triple.getArch() == llvm::Triple::sparc && Triple.isOSSolaris())
+ return "v9";
+ return "";
+}
+
void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args,
std::vector<StringRef> &Features) {
sparc::FloatABI FloatABI = sparc::getSparcFloatABI(D, Args);
if (FloatABI == sparc::FloatABI::Soft)
Features.push_back("+soft-float");
+
+ if (Arg *A = Args.getLastArg(options::OPT_mfsmuld, options::OPT_mno_fsmuld)) {
+ if (A->getOption().matches(options::OPT_mfsmuld))
+ Features.push_back("+fsmuld");
+ else
+ Features.push_back("-fsmuld");
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_mpopc, options::OPT_mno_popc)) {
+ if (A->getOption().matches(options::OPT_mpopc))
+ Features.push_back("+popc");
+ else
+ Features.push_back("-popc");
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_mvis, options::OPT_mno_vis)) {
+ if (A->getOption().matches(options::OPT_mvis))
+ Features.push_back("+vis");
+ else
+ Features.push_back("-vis");
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_mvis2, options::OPT_mno_vis2)) {
+ if (A->getOption().matches(options::OPT_mvis2))
+ Features.push_back("+vis2");
+ else
+ Features.push_back("-vis2");
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_mvis3, options::OPT_mno_vis3)) {
+ if (A->getOption().matches(options::OPT_mvis3))
+ Features.push_back("+vis3");
+ else
+ Features.push_back("-vis3");
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_mhard_quad_float,
+ options::OPT_msoft_quad_float)) {
+ if (A->getOption().matches(options::OPT_mhard_quad_float))
+ Features.push_back("+hard-quad-float");
+ else
+ Features.push_back("-hard-quad-float");
+ }
+
+ if (Args.hasArg(options::OPT_ffixed_g1))
+ Features.push_back("+reserve-g1");
+
+ if (Args.hasArg(options::OPT_ffixed_g2))
+ Features.push_back("+reserve-g2");
+
+ if (Args.hasArg(options::OPT_ffixed_g3))
+ Features.push_back("+reserve-g3");
+
+ if (Args.hasArg(options::OPT_ffixed_g4))
+ Features.push_back("+reserve-g4");
+
+ if (Args.hasArg(options::OPT_ffixed_g5))
+ Features.push_back("+reserve-g5");
+
+ if (Args.hasArg(options::OPT_ffixed_g6))
+ Features.push_back("+reserve-g6");
+
+ if (Args.hasArg(options::OPT_ffixed_g7))
+ Features.push_back("+reserve-g7");
+
+ if (Args.hasArg(options::OPT_ffixed_o0))
+ Features.push_back("+reserve-o0");
+
+ if (Args.hasArg(options::OPT_ffixed_o1))
+ Features.push_back("+reserve-o1");
+
+ if (Args.hasArg(options::OPT_ffixed_o2))
+ Features.push_back("+reserve-o2");
+
+ if (Args.hasArg(options::OPT_ffixed_o3))
+ Features.push_back("+reserve-o3");
+
+ if (Args.hasArg(options::OPT_ffixed_o4))
+ Features.push_back("+reserve-o4");
+
+ if (Args.hasArg(options::OPT_ffixed_o5))
+ Features.push_back("+reserve-o5");
+
+ if (Args.hasArg(options::OPT_ffixed_l0))
+ Features.push_back("+reserve-l0");
+
+ if (Args.hasArg(options::OPT_ffixed_l1))
+ Features.push_back("+reserve-l1");
+
+ if (Args.hasArg(options::OPT_ffixed_l2))
+ Features.push_back("+reserve-l2");
+
+ if (Args.hasArg(options::OPT_ffixed_l3))
+ Features.push_back("+reserve-l3");
+
+ if (Args.hasArg(options::OPT_ffixed_l4))
+ Features.push_back("+reserve-l4");
+
+ if (Args.hasArg(options::OPT_ffixed_l5))
+ Features.push_back("+reserve-l5");
+
+ if (Args.hasArg(options::OPT_ffixed_l6))
+ Features.push_back("+reserve-l6");
+
+ if (Args.hasArg(options::OPT_ffixed_l7))
+ Features.push_back("+reserve-l7");
+
+ if (Args.hasArg(options::OPT_ffixed_i0))
+ Features.push_back("+reserve-i0");
+
+ if (Args.hasArg(options::OPT_ffixed_i1))
+ Features.push_back("+reserve-i1");
+
+ if (Args.hasArg(options::OPT_ffixed_i2))
+ Features.push_back("+reserve-i2");
+
+ if (Args.hasArg(options::OPT_ffixed_i3))
+ Features.push_back("+reserve-i3");
+
+ if (Args.hasArg(options::OPT_ffixed_i4))
+ Features.push_back("+reserve-i4");
+
+ if (Args.hasArg(options::OPT_ffixed_i5))
+ Features.push_back("+reserve-i5");
}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/Sparc.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/Sparc.h
index d12a9a70e264..44658c4259c6 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/Sparc.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/Sparc.h
@@ -28,6 +28,9 @@ enum class FloatABI {
FloatABI getSparcFloatABI(const Driver &D, const llvm::opt::ArgList &Args);
+std::string getSparcTargetCPU(const Driver &D, const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple);
+
void getSparcTargetFeatures(const Driver &D, const llvm::opt::ArgList &Args,
std::vector<llvm::StringRef> &Features);
const char *getSparcAsmModeForCPU(llvm::StringRef Name,
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp
index f81bf68172de..588bc3176d73 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp
@@ -11,7 +11,7 @@
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
-#include "llvm/Support/Host.h"
+#include "llvm/TargetParser/Host.h"
using namespace clang::driver;
using namespace clang::driver::tools;
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/VE.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/VE.cpp
index 9dfd37c2106d..b19760898c64 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/VE.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/VE.cpp
@@ -10,7 +10,6 @@
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
-#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/ArgList.h"
using namespace clang::driver;
@@ -19,4 +18,9 @@ using namespace clang;
using namespace llvm::opt;
void ve::getVETargetFeatures(const Driver &D, const ArgList &Args,
- std::vector<StringRef> &Features) {}
+ std::vector<StringRef> &Features) {
+ if (Args.hasFlag(options::OPT_mvevpu, options::OPT_mno_vevpu, true))
+ Features.push_back("+vpu");
+ else
+ Features.push_back("-vpu");
+}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/VE.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/VE.h
index 531433534914..c47a41df25bc 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/VE.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/VE.h
@@ -24,7 +24,7 @@ void getVETargetFeatures(const Driver &D, const llvm::opt::ArgList &Args,
std::vector<llvm::StringRef> &Features);
} // end namespace ve
-} // namespace tools
+} // end namespace tools
} // end namespace driver
} // end namespace clang
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/X86.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/X86.cpp
index 12749c7ec871..53e26a9f8e22 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/X86.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/X86.cpp
@@ -11,16 +11,17 @@
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
-#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/Option/ArgList.h"
-#include "llvm/Support/Host.h"
+#include "llvm/TargetParser/Host.h"
using namespace clang::driver;
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();
@@ -29,37 +30,39 @@ std::string x86::getX86TargetCPU(const ArgList &Args,
// FIXME: Reject attempts to use -march=native unless the target matches
// the host.
- //
- // FIXME: We should also incorporate the detected target features for use
- // with -native.
CPU = llvm::sys::getHostCPUName();
if (!CPU.empty() && CPU != "generic")
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).
@@ -77,13 +80,19 @@ std::string x86::getX86TargetCPU(const ArgList &Args,
// Simulators can still run on 10.11 though, like Xcode.
if (Triple.isMacOSX() && !Triple.isOSVersionLT(10, 12))
return "penryn";
+
+ if (Triple.isDriverKit())
+ return "nehalem";
+
// The oldest x86_64 Macs have core2/Merom; the oldest x86 Macs have Yonah.
return Is64Bit ? "core2" : "yonah";
}
- // Set up default CPU name for PS4 compilers.
- if (Triple.isPS4CPU())
+ // Set up default CPU name for PS4/PS5 compilers.
+ if (Triple.isPS4())
return "btver2";
+ if (Triple.isPS5())
+ return "znver2";
// On Android use targets compatible with gcc
if (Triple.isAndroid())
@@ -110,6 +119,15 @@ std::string x86::getX86TargetCPU(const ArgList &Args,
void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args,
std::vector<StringRef> &Features) {
+ // Claim and report unsupported -mabi=. Note: we don't support "sysv_abi" or
+ // "ms_abi" as default function attributes.
+ if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mabi_EQ)) {
+ StringRef DefaultAbi = Triple.isOSWindows() ? "ms" : "sysv";
+ if (A->getValue() != DefaultAbi)
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getSpelling() << Triple.getTriple();
+ }
+
// If -march=native, autodetect the feature list.
if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ)) {
if (StringRef(A->getValue()) == "native") {
@@ -211,6 +229,27 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
<< D.getOpts().getOptionName(LVIOpt);
}
+ for (const Arg *A : Args.filtered(options::OPT_m_x86_AVX10_Features_Group)) {
+ StringRef Name = A->getOption().getName();
+ A->claim();
+
+ // Skip over "-m".
+ assert(Name.starts_with("m") && "Invalid feature name.");
+ Name = Name.substr(1);
+
+ bool IsNegative = Name.consume_front("no-");
+
+#ifndef NDEBUG
+ assert(Name.starts_with("avx10.") && "Invalid AVX10 feature name.");
+ StringRef Version, Width;
+ std::tie(Version, Width) = Name.substr(6).split('-');
+ assert(Version == "1" && "Invalid AVX10 feature name.");
+ assert((Width == "256" || Width == "512") && "Invalid AVX10 feature name.");
+#endif
+
+ Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
+ }
+
// Now add any that the user explicitly requested on the command line,
// which may override the defaults.
for (const Arg *A : Args.filtered(options::OPT_m_x86_Features_Group,
@@ -219,7 +258,7 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
A->claim();
// Skip over "-m".
- assert(Name.startswith("m") && "Invalid feature name.");
+ assert(Name.starts_with("m") && "Invalid feature name.");
Name = Name.substr(1);
// Replace -mgeneral-regs-only with -x87, -mmx, -sse
@@ -228,9 +267,46 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
continue;
}
- bool IsNegative = Name.startswith("no-");
+ bool IsNegative = Name.starts_with("no-");
+ if (A->getOption().matches(options::OPT_mapx_features_EQ) ||
+ A->getOption().matches(options::OPT_mno_apx_features_EQ)) {
+
+ for (StringRef Value : A->getValues()) {
+ if (Value == "egpr" || Value == "push2pop2" || Value == "ppx" ||
+ Value == "ndd" || Value == "ccmp" || Value == "cf") {
+ Features.push_back(
+ Args.MakeArgString((IsNegative ? "-" : "+") + Value));
+ continue;
+ }
+ D.Diag(clang::diag::err_drv_unsupported_option_argument)
+ << A->getSpelling() << Value;
+ }
+ continue;
+ }
if (IsNegative)
Name = Name.substr(3);
Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
}
+
+ // Enable/disable straight line speculation hardening.
+ if (Arg *A = Args.getLastArg(options::OPT_mharden_sls_EQ)) {
+ StringRef Scope = A->getValue();
+ if (Scope == "all") {
+ Features.push_back("+harden-sls-ijmp");
+ Features.push_back("+harden-sls-ret");
+ } else if (Scope == "return") {
+ Features.push_back("+harden-sls-ret");
+ } else if (Scope == "indirect-jmp") {
+ Features.push_back("+harden-sls-ijmp");
+ } else if (Scope != "none") {
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getSpelling() << Scope;
+ }
+ }
+
+ // -mno-gather, -mno-scatter support
+ if (Args.hasArg(options::OPT_mno_gather))
+ Features.push_back("+prefer-no-gather");
+ if (Args.hasArg(options::OPT_mno_scatter))
+ Features.push_back("+prefer-no-scatter");
}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/X86.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/X86.h
index 14f0a26c8be4..e07387f3ece3 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/X86.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/X86.h
@@ -11,8 +11,8 @@
#include "clang/Driver/Driver.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/Option/Option.h"
+#include "llvm/TargetParser/Triple.h"
#include <string>
#include <vector>
@@ -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/contrib/llvm-project/clang/lib/Driver/ToolChains/BareMetal.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/BareMetal.cpp
index ce73e39d1456..391c47f88bde 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -12,26 +12,27 @@
#include "Gnu.h"
#include "clang/Driver/InputInfo.h"
+#include "Arch/ARM.h"
#include "Arch/RISCV.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/MultilibBuilder.h"
#include "clang/Driver/Options.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
+#include <sstream>
+
using namespace llvm::opt;
using namespace clang;
using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang::driver::toolchains;
-static Multilib makeMultilib(StringRef commonSuffix) {
- return Multilib(commonSuffix, commonSuffix, commonSuffix);
-}
-
static bool findRISCVMultilibs(const Driver &D,
const llvm::Triple &TargetTriple,
const ArgList &Args, DetectedMultilibs &Result) {
@@ -39,37 +40,41 @@ static bool findRISCVMultilibs(const Driver &D,
StringRef Arch = riscv::getRISCVArch(Args, TargetTriple);
StringRef Abi = tools::riscv::getRISCVABI(Args, TargetTriple);
- if (TargetTriple.getArch() == llvm::Triple::riscv64) {
- Multilib Imac = makeMultilib("").flag("+march=rv64imac").flag("+mabi=lp64");
- Multilib Imafdc = makeMultilib("/rv64imafdc/lp64d")
- .flag("+march=rv64imafdc")
- .flag("+mabi=lp64d");
+ if (TargetTriple.isRISCV64()) {
+ MultilibBuilder Imac =
+ MultilibBuilder().flag("-march=rv64imac").flag("-mabi=lp64");
+ MultilibBuilder Imafdc = MultilibBuilder("/rv64imafdc/lp64d")
+ .flag("-march=rv64imafdc")
+ .flag("-mabi=lp64d");
// Multilib reuse
bool UseImafdc =
(Arch == "rv64imafdc") || (Arch == "rv64gc"); // gc => imafdc
- addMultilibFlag((Arch == "rv64imac"), "march=rv64imac", Flags);
- addMultilibFlag(UseImafdc, "march=rv64imafdc", Flags);
- addMultilibFlag(Abi == "lp64", "mabi=lp64", Flags);
- addMultilibFlag(Abi == "lp64d", "mabi=lp64d", Flags);
+ addMultilibFlag((Arch == "rv64imac"), "-march=rv64imac", Flags);
+ addMultilibFlag(UseImafdc, "-march=rv64imafdc", Flags);
+ addMultilibFlag(Abi == "lp64", "-mabi=lp64", Flags);
+ addMultilibFlag(Abi == "lp64d", "-mabi=lp64d", Flags);
- Result.Multilibs = MultilibSet().Either(Imac, Imafdc);
- return Result.Multilibs.select(Flags, Result.SelectedMultilib);
+ Result.Multilibs =
+ MultilibSetBuilder().Either(Imac, Imafdc).makeMultilibSet();
+ return Result.Multilibs.select(Flags, Result.SelectedMultilibs);
}
- if (TargetTriple.getArch() == llvm::Triple::riscv32) {
- Multilib Imac =
- makeMultilib("").flag("+march=rv32imac").flag("+mabi=ilp32");
- Multilib I =
- makeMultilib("/rv32i/ilp32").flag("+march=rv32i").flag("+mabi=ilp32");
- Multilib Im =
- makeMultilib("/rv32im/ilp32").flag("+march=rv32im").flag("+mabi=ilp32");
- Multilib Iac = makeMultilib("/rv32iac/ilp32")
- .flag("+march=rv32iac")
- .flag("+mabi=ilp32");
- Multilib Imafc = makeMultilib("/rv32imafc/ilp32f")
- .flag("+march=rv32imafc")
- .flag("+mabi=ilp32f");
+ if (TargetTriple.isRISCV32()) {
+ MultilibBuilder Imac =
+ MultilibBuilder().flag("-march=rv32imac").flag("-mabi=ilp32");
+ MultilibBuilder I = MultilibBuilder("/rv32i/ilp32")
+ .flag("-march=rv32i")
+ .flag("-mabi=ilp32");
+ MultilibBuilder Im = MultilibBuilder("/rv32im/ilp32")
+ .flag("-march=rv32im")
+ .flag("-mabi=ilp32");
+ MultilibBuilder Iac = MultilibBuilder("/rv32iac/ilp32")
+ .flag("-march=rv32iac")
+ .flag("-mabi=ilp32");
+ MultilibBuilder Imafc = MultilibBuilder("/rv32imafc/ilp32f")
+ .flag("-march=rv32imafc")
+ .flag("-mabi=ilp32f");
// Multilib reuse
bool UseI = (Arch == "rv32i") || (Arch == "rv32ic"); // ic => i
@@ -77,22 +82,23 @@ static bool findRISCVMultilibs(const Driver &D,
bool UseImafc = (Arch == "rv32imafc") || (Arch == "rv32imafdc") ||
(Arch == "rv32gc"); // imafdc,gc => imafc
- addMultilibFlag(UseI, "march=rv32i", Flags);
- addMultilibFlag(UseIm, "march=rv32im", Flags);
- addMultilibFlag((Arch == "rv32iac"), "march=rv32iac", Flags);
- addMultilibFlag((Arch == "rv32imac"), "march=rv32imac", Flags);
- addMultilibFlag(UseImafc, "march=rv32imafc", Flags);
- addMultilibFlag(Abi == "ilp32", "mabi=ilp32", Flags);
- addMultilibFlag(Abi == "ilp32f", "mabi=ilp32f", Flags);
-
- Result.Multilibs = MultilibSet().Either(I, Im, Iac, Imac, Imafc);
- return Result.Multilibs.select(Flags, Result.SelectedMultilib);
+ addMultilibFlag(UseI, "-march=rv32i", Flags);
+ addMultilibFlag(UseIm, "-march=rv32im", Flags);
+ addMultilibFlag((Arch == "rv32iac"), "-march=rv32iac", Flags);
+ addMultilibFlag((Arch == "rv32imac"), "-march=rv32imac", Flags);
+ addMultilibFlag(UseImafc, "-march=rv32imafc", Flags);
+ addMultilibFlag(Abi == "ilp32", "-mabi=ilp32", Flags);
+ addMultilibFlag(Abi == "ilp32f", "-mabi=ilp32f", Flags);
+
+ Result.Multilibs =
+ MultilibSetBuilder().Either(I, Im, Iac, Imac, Imafc).makeMultilibSet();
+ return Result.Multilibs.select(Flags, Result.SelectedMultilibs);
}
return false;
}
BareMetal::BareMetal(const Driver &D, const llvm::Triple &Triple,
- const ArgList &Args)
+ const ArgList &Args)
: ToolChain(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
@@ -101,15 +107,21 @@ BareMetal::BareMetal(const Driver &D, const llvm::Triple &Triple,
findMultilibs(D, Triple, Args);
SmallString<128> SysRoot(computeSysRoot());
if (!SysRoot.empty()) {
- llvm::sys::path::append(SysRoot, "lib");
- getFilePaths().push_back(std::string(SysRoot));
+ for (const Multilib &M : getOrderedMultilibs()) {
+ SmallString<128> Dir(SysRoot);
+ llvm::sys::path::append(Dir, M.osSuffix(), "lib");
+ getFilePaths().push_back(std::string(Dir));
+ getLibraryPaths().push_back(std::string(Dir));
+ }
}
}
-/// Is the triple {arm,thumb}-none-none-{eabi,eabihf} ?
+/// Is the triple {arm,armeb,thumb,thumbeb}-none-none-{eabi,eabihf} ?
static bool isARMBareMetal(const llvm::Triple &Triple) {
if (Triple.getArch() != llvm::Triple::arm &&
- Triple.getArch() != llvm::Triple::thumb)
+ Triple.getArch() != llvm::Triple::thumb &&
+ Triple.getArch() != llvm::Triple::armeb &&
+ Triple.getArch() != llvm::Triple::thumbeb)
return false;
if (Triple.getVendor() != llvm::Triple::UnknownVendor)
@@ -125,9 +137,23 @@ static bool isARMBareMetal(const llvm::Triple &Triple) {
return true;
}
+/// Is the triple {aarch64.aarch64_be}-none-elf?
+static bool isAArch64BareMetal(const llvm::Triple &Triple) {
+ if (Triple.getArch() != llvm::Triple::aarch64 &&
+ Triple.getArch() != llvm::Triple::aarch64_be)
+ 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)
+ if (!Triple.isRISCV())
return false;
if (Triple.getVendor() != llvm::Triple::UnknownVendor)
@@ -139,50 +165,100 @@ static bool isRISCVBareMetal(const llvm::Triple &Triple) {
return Triple.getEnvironmentName() == "elf";
}
+/// Is the triple powerpc[64][le]-*-none-eabi?
+static bool isPPCBareMetal(const llvm::Triple &Triple) {
+ return Triple.isPPC() && Triple.getOS() == llvm::Triple::UnknownOS &&
+ Triple.getEnvironment() == llvm::Triple::EABI;
+}
+
+static void findMultilibsFromYAML(const ToolChain &TC, const Driver &D,
+ StringRef MultilibPath, const ArgList &Args,
+ DetectedMultilibs &Result) {
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MB =
+ D.getVFS().getBufferForFile(MultilibPath);
+ if (!MB)
+ return;
+ Multilib::flags_list Flags = TC.getMultilibFlags(Args);
+ llvm::ErrorOr<MultilibSet> ErrorOrMultilibSet =
+ MultilibSet::parseYaml(*MB.get());
+ if (ErrorOrMultilibSet.getError())
+ return;
+ Result.Multilibs = ErrorOrMultilibSet.get();
+ if (Result.Multilibs.select(Flags, Result.SelectedMultilibs))
+ return;
+ D.Diag(clang::diag::warn_drv_missing_multilib) << llvm::join(Flags, " ");
+ std::stringstream ss;
+ for (const Multilib &Multilib : Result.Multilibs)
+ ss << "\n" << llvm::join(Multilib.flags(), " ");
+ D.Diag(clang::diag::note_drv_available_multilibs) << ss.str();
+}
+
+static constexpr llvm::StringLiteral MultilibFilename = "multilib.yaml";
+
+// Get the sysroot, before multilib takes effect.
+static std::string computeBaseSysRoot(const Driver &D,
+ const llvm::Triple &Triple) {
+ if (!D.SysRoot.empty())
+ return D.SysRoot;
+
+ SmallString<128> SysRootDir(D.Dir);
+ llvm::sys::path::append(SysRootDir, "..", "lib", "clang-runtimes");
+
+ SmallString<128> MultilibPath(SysRootDir);
+ llvm::sys::path::append(MultilibPath, MultilibFilename);
+
+ // New behaviour: if multilib.yaml is found then use clang-runtimes as the
+ // sysroot.
+ if (D.getVFS().exists(MultilibPath))
+ return std::string(SysRootDir);
+
+ // Otherwise fall back to the old behaviour of appending the target triple.
+ llvm::sys::path::append(SysRootDir, D.getTargetTriple());
+ return std::string(SysRootDir);
+}
+
void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args) {
DetectedMultilibs Result;
if (isRISCVBareMetal(Triple)) {
if (findRISCVMultilibs(D, Triple, Args, Result)) {
- SelectedMultilib = Result.SelectedMultilib;
+ SelectedMultilibs = Result.SelectedMultilibs;
Multilibs = Result.Multilibs;
}
+ } else {
+ llvm::SmallString<128> MultilibPath(computeBaseSysRoot(D, Triple));
+ llvm::sys::path::append(MultilibPath, MultilibFilename);
+ findMultilibsFromYAML(*this, D, MultilibPath, Args, Result);
+ SelectedMultilibs = Result.SelectedMultilibs;
+ Multilibs = Result.Multilibs;
}
}
bool BareMetal::handlesTarget(const llvm::Triple &Triple) {
- return isARMBareMetal(Triple) || isRISCVBareMetal(Triple);
+ return isARMBareMetal(Triple) || isAArch64BareMetal(Triple) ||
+ isRISCVBareMetal(Triple) || isPPCBareMetal(Triple);
}
Tool *BareMetal::buildLinker() const {
return new tools::baremetal::Linker(*this);
}
-std::string BareMetal::getCompilerRTPath() const { return getRuntimesDir(); }
-
-std::string BareMetal::buildCompilerRTBasename(const llvm::opt::ArgList &,
- StringRef, FileType,
- bool) const {
- return ("libclang_rt.builtins-" + getTriple().getArchName() + ".a").str();
-}
-
-std::string BareMetal::getRuntimesDir() const {
- SmallString<128> Dir(getDriver().ResourceDir);
- llvm::sys::path::append(Dir, "lib", "baremetal");
- Dir += SelectedMultilib.gccSuffix();
- return std::string(Dir.str());
+Tool *BareMetal::buildStaticLibTool() const {
+ return new tools::baremetal::StaticLibTool(*this);
}
std::string BareMetal::computeSysRoot() const {
- if (!getDriver().SysRoot.empty())
- return getDriver().SysRoot + SelectedMultilib.osSuffix();
+ return computeBaseSysRoot(getDriver(), getTriple());
+}
- SmallString<128> SysRootDir;
- llvm::sys::path::append(SysRootDir, getDriver().Dir, "../lib/clang-runtimes",
- getDriver().getTargetTriple());
+BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs() const {
+ // Get multilibs in reverse order because they're ordered most-specific last.
+ if (!SelectedMultilibs.empty())
+ return llvm::reverse(SelectedMultilibs);
- SysRootDir += SelectedMultilib.osSuffix();
- return std::string(SysRootDir);
+ // No multilibs selected so return a single default multilib.
+ static const llvm::SmallVector<Multilib> Default = {Multilib()};
+ return llvm::reverse(Default);
}
void BareMetal::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
@@ -197,10 +273,14 @@ void BareMetal::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
}
if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
- SmallString<128> Dir(computeSysRoot());
- if (!Dir.empty()) {
- llvm::sys::path::append(Dir, "include");
- addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ const SmallString<128> SysRoot(computeSysRoot());
+ if (!SysRoot.empty()) {
+ for (const Multilib &M : getOrderedMultilibs()) {
+ SmallString<128> Dir(SysRoot);
+ llvm::sys::path::append(Dir, M.includeSuffix());
+ llvm::sys::path::append(Dir, "include");
+ addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ }
}
}
}
@@ -211,48 +291,58 @@ void BareMetal::addClangTargetOptions(const ArgList &DriverArgs,
CC1Args.push_back("-nostdsysteminc");
}
-void BareMetal::AddClangCXXStdlibIncludeArgs(
- const ArgList &DriverArgs, ArgStringList &CC1Args) const {
- if (DriverArgs.hasArg(options::OPT_nostdinc) ||
- DriverArgs.hasArg(options::OPT_nostdlibinc) ||
- DriverArgs.hasArg(options::OPT_nostdincxx))
+void BareMetal::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc,
+ options::OPT_nostdincxx))
return;
+ const Driver &D = getDriver();
std::string SysRoot(computeSysRoot());
if (SysRoot.empty())
return;
- switch (GetCXXStdlibType(DriverArgs)) {
- case ToolChain::CST_Libcxx: {
+ for (const Multilib &M : getOrderedMultilibs()) {
SmallString<128> Dir(SysRoot);
- llvm::sys::path::append(Dir, "include", "c++", "v1");
- addSystemInclude(DriverArgs, CC1Args, Dir.str());
- break;
- }
- case ToolChain::CST_Libstdcxx: {
- SmallString<128> Dir(SysRoot);
- llvm::sys::path::append(Dir, "include", "c++");
- std::error_code EC;
- Generic_GCC::GCCVersion Version = {"", -1, -1, -1, "", "", ""};
- // Walk the subdirs, and find the one with the newest gcc version:
- for (llvm::vfs::directory_iterator
- LI = getDriver().getVFS().dir_begin(Dir.str(), EC),
- LE;
- !EC && LI != LE; LI = LI.increment(EC)) {
- StringRef VersionText = llvm::sys::path::filename(LI->path());
- auto CandidateVersion = Generic_GCC::GCCVersion::Parse(VersionText);
- if (CandidateVersion.Major == -1)
- continue;
- if (CandidateVersion <= Version)
- continue;
- Version = CandidateVersion;
+ llvm::sys::path::append(Dir, M.gccSuffix());
+ switch (GetCXXStdlibType(DriverArgs)) {
+ case ToolChain::CST_Libcxx: {
+ // First check sysroot/usr/include/c++/v1 if it exists.
+ SmallString<128> TargetDir(Dir);
+ llvm::sys::path::append(TargetDir, "usr", "include", "c++", "v1");
+ if (D.getVFS().exists(TargetDir)) {
+ addSystemInclude(DriverArgs, CC1Args, TargetDir.str());
+ break;
+ }
+ // Add generic path if nothing else succeeded so far.
+ llvm::sys::path::append(Dir, "include", "c++", "v1");
+ addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ break;
+ }
+ case ToolChain::CST_Libstdcxx: {
+ llvm::sys::path::append(Dir, "include", "c++");
+ std::error_code EC;
+ Generic_GCC::GCCVersion Version = {"", -1, -1, -1, "", "", ""};
+ // Walk the subdirs, and find the one with the newest gcc version:
+ for (llvm::vfs::directory_iterator
+ LI = D.getVFS().dir_begin(Dir.str(), EC),
+ LE;
+ !EC && LI != LE; LI = LI.increment(EC)) {
+ StringRef VersionText = llvm::sys::path::filename(LI->path());
+ auto CandidateVersion = Generic_GCC::GCCVersion::Parse(VersionText);
+ if (CandidateVersion.Major == -1)
+ continue;
+ if (CandidateVersion <= Version)
+ continue;
+ Version = CandidateVersion;
+ }
+ if (Version.Major != -1) {
+ llvm::sys::path::append(Dir, Version.Text);
+ addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ }
+ break;
+ }
}
- if (Version.Major == -1)
- return;
- llvm::sys::path::append(Dir, Version.Text);
- addSystemInclude(DriverArgs, CC1Args, Dir.str());
- break;
- }
}
}
@@ -261,6 +351,8 @@ void BareMetal::AddCXXStdlibLibArgs(const ArgList &Args,
switch (GetCXXStdlibType(Args)) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back("-lc++abi");
break;
case ToolChain::CST_Libstdcxx:
@@ -275,10 +367,14 @@ void BareMetal::AddLinkRuntimeLib(const ArgList &Args,
ArgStringList &CmdArgs) const {
ToolChain::RuntimeLibType RLT = GetRuntimeLibType(Args);
switch (RLT) {
- case ToolChain::RLT_CompilerRT:
- CmdArgs.push_back(
- Args.MakeArgString("-lclang_rt.builtins-" + getTriple().getArchName()));
+ case ToolChain::RLT_CompilerRT: {
+ const std::string FileName = getCompilerRT(Args, "builtins");
+ llvm::StringRef BaseName = llvm::sys::path::filename(FileName);
+ BaseName.consume_front("lib");
+ BaseName.consume_back(".a");
+ CmdArgs.push_back(Args.MakeArgString("-l" + BaseName));
return;
+ }
case ToolChain::RLT_Libgcc:
CmdArgs.push_back("-lgcc");
return;
@@ -286,6 +382,51 @@ void BareMetal::AddLinkRuntimeLib(const ArgList &Args,
llvm_unreachable("Unhandled RuntimeLibType.");
}
+void baremetal::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);
+
+ // ar tool command "llvm-ar <options> <output_file> <input_files>".
+ ArgStringList CmdArgs;
+ // Create and insert file members with a deterministic index.
+ CmdArgs.push_back("rcsD");
+ 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 char *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::AtFileCurCP(),
+ Exec, CmdArgs, Inputs, Output));
+}
+
void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -293,22 +434,39 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const char *LinkingOutput) const {
ArgStringList CmdArgs;
- auto &TC = static_cast<const toolchains::BareMetal&>(getToolChain());
+ auto &TC = static_cast<const toolchains::BareMetal &>(getToolChain());
+ const llvm::Triple::ArchType Arch = TC.getArch();
+ const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
CmdArgs.push_back("-Bstatic");
- Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
- options::OPT_e, options::OPT_s, options::OPT_t,
- options::OPT_Z_Flag, options::OPT_r});
+ if (Triple.isARM() || Triple.isThumb()) {
+ bool IsBigEndian = arm::isARMBigEndian(Triple, Args);
+ if (IsBigEndian)
+ arm::appendBE8LinkFlag(Args, CmdArgs, Triple);
+ CmdArgs.push_back(IsBigEndian ? "-EB" : "-EL");
+ } else if (Triple.isAArch64()) {
+ CmdArgs.push_back(Arch == llvm::Triple::aarch64_be ? "-EB" : "-EL");
+ }
+
+ Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
+ options::OPT_s, options::OPT_t, options::OPT_r});
TC.AddFilePathLibArgs(Args, CmdArgs);
- CmdArgs.push_back(Args.MakeArgString("-L" + TC.getRuntimesDir()));
+ for (const auto &LibPath : TC.getLibraryPaths())
+ CmdArgs.push_back(Args.MakeArgString(llvm::Twine("-L", LibPath)));
+
+ const std::string FileName = TC.getCompilerRT(Args, "builtins");
+ llvm::SmallString<128> PathBuf{FileName};
+ llvm::sys::path::remove_filename(PathBuf);
+ CmdArgs.push_back(Args.MakeArgString("-L" + PathBuf));
if (TC.ShouldLinkCXXStdlib(Args))
TC.AddCXXStdlibLibArgs(Args, CmdArgs);
+
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
CmdArgs.push_back("-lc");
CmdArgs.push_back("-lm");
@@ -316,10 +474,45 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
TC.AddLinkRuntimeLib(Args, CmdArgs);
}
+ if (TC.getTriple().isRISCV())
+ CmdArgs.push_back("-X");
+
+ // The R_ARM_TARGET2 relocation must be treated as R_ARM_REL32 on arm*-*-elf
+ // and arm*-*-eabi (the default is R_ARM_GOT_PREL, used on arm*-*-linux and
+ // arm*-*-*bsd).
+ if (isARMBareMetal(TC.getTriple()))
+ CmdArgs.push_back("--target2=rel");
+
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
- Args.MakeArgString(TC.GetLinkerPath()),
- CmdArgs, Inputs, Output));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(),
+ Args.MakeArgString(TC.GetLinkerPath()), CmdArgs, Inputs, Output));
+}
+
+// BareMetal toolchain allows all sanitizers where the compiler generates valid
+// code, ignoring all runtime library support issues on the assumption that
+// baremetal targets typically implement their own runtime support.
+SanitizerMask BareMetal::getSupportedSanitizers() const {
+ const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
+ const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64 ||
+ getTriple().getArch() == llvm::Triple::aarch64_be;
+ const bool IsRISCV64 = getTriple().getArch() == llvm::Triple::riscv64;
+ SanitizerMask Res = ToolChain::getSupportedSanitizers();
+ Res |= SanitizerKind::Address;
+ Res |= SanitizerKind::KernelAddress;
+ Res |= SanitizerKind::PointerCompare;
+ Res |= SanitizerKind::PointerSubtract;
+ Res |= SanitizerKind::Fuzzer;
+ Res |= SanitizerKind::FuzzerNoLink;
+ Res |= SanitizerKind::Vptr;
+ Res |= SanitizerKind::SafeStack;
+ Res |= SanitizerKind::Thread;
+ Res |= SanitizerKind::Scudo;
+ if (IsX86_64 || IsAArch64 || IsRISCV64) {
+ Res |= SanitizerKind::HWAddress;
+ Res |= SanitizerKind::KernelHWAddress;
+ }
+ return Res;
}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/BareMetal.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/BareMetal.h
index d68c43c64c97..67b5aa5998fc 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/BareMetal.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/BareMetal.h
@@ -1,4 +1,4 @@
-//===--- BareMetal.h - Bare Metal Tool and ToolChain -------------*- C++ -*-===//
+//===--- BareMetal.h - Bare Metal Tool and ToolChain ------------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -32,24 +32,22 @@ public:
protected:
Tool *buildLinker() const override;
-
- std::string buildCompilerRTBasename(const llvm::opt::ArgList &Args,
- StringRef Component,
- FileType Type = ToolChain::FT_Static,
- bool AddArch = true) const override;
+ Tool *buildStaticLibTool() const override;
public:
bool useIntegratedAs() const override { return true; }
+ bool isBareMetal() const override { return true; }
bool isCrossCompiling() const override { return true; }
+ bool HasNativeLLVMSupport() 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; }
StringRef getOSLibName() const override { return "baremetal"; }
- std::string getCompilerRTPath() const override;
-
RuntimeLibType GetDefaultRuntimeLibType() const override {
return ToolChain::RLT_CompilerRT;
}
@@ -59,12 +57,13 @@ public:
const char *getDefaultLinker() const override { return "ld.lld"; }
- std::string getRuntimesDir() const;
- void 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;
+ void
+ 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;
void AddClangCXXStdlibIncludeArgs(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
@@ -73,6 +72,12 @@ public:
void AddLinkRuntimeLib(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
std::string computeSysRoot() const override;
+ SanitizerMask getSupportedSanitizers() const override;
+
+private:
+ using OrderedMultilibs =
+ llvm::iterator_range<llvm::SmallVector<Multilib>::const_reverse_iterator>;
+ OrderedMultilibs getOrderedMultilibs() const;
};
} // namespace toolchains
@@ -80,7 +85,21 @@ public:
namespace tools {
namespace baremetal {
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+class LLVM_LIBRARY_VISIBILITY StaticLibTool : public Tool {
+public:
+ StaticLibTool(const ToolChain &TC)
+ : Tool("baremetal::StaticLibTool", "llvm-ar", 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 Linker final : public Tool {
public:
Linker(const ToolChain &TC) : Tool("baremetal::Linker", "ld.lld", TC) {}
bool isLinkJob() const override { return true; }
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/CSKYToolChain.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/CSKYToolChain.cpp
new file mode 100644
index 000000000000..feb3bc922920
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/CSKYToolChain.cpp
@@ -0,0 +1,204 @@
+//===--- CSKYToolchain.cpp - CSKY ToolChain Implementations ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "CSKYToolChain.h"
+#include "CommonArgs.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/InputInfo.h"
+#include "clang/Driver/Options.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+static void addMultilibsFilePaths(const Driver &D, const MultilibSet &Multilibs,
+ const Multilib &Multilib,
+ StringRef InstallPath,
+ ToolChain::path_list &Paths) {
+ if (const auto &PathsCallback = Multilibs.filePathsCallback())
+ for (const auto &Path : PathsCallback(Multilib))
+ addPathIfExists(D, InstallPath + Path, Paths);
+}
+
+/// CSKY Toolchain
+CSKYToolChain::CSKYToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
+ GCCInstallation.init(Triple, Args);
+ if (GCCInstallation.isValid()) {
+ Multilibs = GCCInstallation.getMultilibs();
+ SelectedMultilibs.assign({GCCInstallation.getMultilib()});
+ path_list &Paths = getFilePaths();
+ // Add toolchain/multilib specific file paths.
+ addMultilibsFilePaths(D, Multilibs, SelectedMultilibs.back(),
+ GCCInstallation.getInstallPath(), Paths);
+ getFilePaths().push_back(GCCInstallation.getInstallPath().str() +
+ SelectedMultilibs.back().osSuffix());
+ ToolChain::path_list &PPaths = getProgramPaths();
+ // Multilib cross-compiler GCC installations put ld in a triple-prefixed
+ // directory off of the parent of the GCC installation.
+ PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +
+ GCCInstallation.getTriple().str() + "/bin")
+ .str());
+ PPaths.push_back((GCCInstallation.getParentLibPath() + "/../bin").str());
+ getFilePaths().push_back(computeSysRoot() + "/lib" +
+ SelectedMultilibs.back().osSuffix());
+ } else {
+ getProgramPaths().push_back(D.Dir);
+ getFilePaths().push_back(computeSysRoot() + "/lib");
+ }
+}
+
+Tool *CSKYToolChain::buildLinker() const {
+ return new tools::CSKY::Linker(*this);
+}
+
+ToolChain::RuntimeLibType CSKYToolChain::GetDefaultRuntimeLibType() const {
+ return GCCInstallation.isValid() ? ToolChain::RLT_Libgcc
+ : ToolChain::RLT_CompilerRT;
+}
+
+ToolChain::UnwindLibType
+CSKYToolChain::GetUnwindLibType(const llvm::opt::ArgList &Args) const {
+ return ToolChain::UNW_None;
+}
+
+void CSKYToolChain::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind) const {
+ CC1Args.push_back("-nostdsysteminc");
+}
+
+void CSKYToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdinc))
+ return;
+
+ if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
+ SmallString<128> Dir(computeSysRoot());
+ llvm::sys::path::append(Dir, "include");
+ addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ SmallString<128> Dir2(computeSysRoot());
+ llvm::sys::path::append(Dir2, "sys-include");
+ addSystemInclude(DriverArgs, CC1Args, Dir2.str());
+ }
+}
+
+void CSKYToolChain::addLibStdCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ const GCCVersion &Version = GCCInstallation.getVersion();
+ StringRef TripleStr = GCCInstallation.getTriple().str();
+ const Multilib &Multilib = GCCInstallation.getMultilib();
+ addLibStdCXXIncludePaths(computeSysRoot() + "/include/c++/" + Version.Text,
+ TripleStr, Multilib.includeSuffix(), DriverArgs,
+ CC1Args);
+}
+
+std::string CSKYToolChain::computeSysRoot() const {
+ if (!getDriver().SysRoot.empty())
+ return getDriver().SysRoot;
+
+ SmallString<128> SysRootDir;
+ if (GCCInstallation.isValid()) {
+ StringRef LibDir = GCCInstallation.getParentLibPath();
+ StringRef TripleStr = GCCInstallation.getTriple().str();
+ llvm::sys::path::append(SysRootDir, LibDir, "..", TripleStr);
+ } else {
+ // Use the triple as provided to the driver. Unlike the parsed triple
+ // this has not been normalized to always contain every field.
+ llvm::sys::path::append(SysRootDir, getDriver().Dir, "..",
+ getDriver().getTargetTriple());
+ }
+
+ if (!llvm::sys::fs::exists(SysRootDir))
+ return std::string();
+
+ return std::string(SysRootDir);
+}
+
+void CSKY::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const ToolChain &ToolChain = getToolChain();
+ const Driver &D = ToolChain.getDriver();
+ ArgStringList CmdArgs;
+
+ if (!D.SysRoot.empty())
+ CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+
+ CmdArgs.push_back("-m");
+ CmdArgs.push_back("cskyelf");
+
+ std::string Linker = getToolChain().GetLinkerPath();
+
+ bool WantCRTs =
+ !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles);
+
+ const char *crtbegin, *crtend;
+ auto RuntimeLib = ToolChain.GetRuntimeLibType(Args);
+ if (RuntimeLib == ToolChain::RLT_Libgcc) {
+ crtbegin = "crtbegin.o";
+ crtend = "crtend.o";
+ } else {
+ assert(RuntimeLib == ToolChain::RLT_CompilerRT);
+ crtbegin = ToolChain.getCompilerRTArgString(Args, "crtbegin",
+ ToolChain::FT_Object);
+ crtend =
+ ToolChain.getCompilerRTArgString(Args, "crtend", ToolChain::FT_Object);
+ }
+
+ if (WantCRTs) {
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ ToolChain.AddFilePathLibArgs(Args, CmdArgs);
+ Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s,
+ options::OPT_t, options::OPT_r});
+
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
+
+ // TODO: add C++ includes and libs if compiling C++.
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (ToolChain.ShouldLinkCXXStdlib(Args))
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ CmdArgs.push_back("--start-group");
+ CmdArgs.push_back("-lc");
+ if (Args.hasArg(options::OPT_msim))
+ CmdArgs.push_back("-lsemi");
+ else
+ CmdArgs.push_back("-lnosys");
+ CmdArgs.push_back("--end-group");
+ AddRunTimeLibs(ToolChain, ToolChain.getDriver(), CmdArgs, Args);
+ }
+
+ if (WantCRTs) {
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
+ }
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Args.MakeArgString(Linker),
+ CmdArgs, Inputs, Output));
+}
+// CSKY tools end.
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/CSKYToolChain.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/CSKYToolChain.h
new file mode 100644
index 000000000000..a57324a42641
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/CSKYToolChain.h
@@ -0,0 +1,63 @@
+//===--- CSKYToolchain.h - CSKY ToolChain Implementations -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CSKYTOOLCHAIN_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CSKYTOOLCHAIN_H
+
+#include "Gnu.h"
+#include "clang/Driver/ToolChain.h"
+
+namespace clang {
+namespace driver {
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY CSKYToolChain : public Generic_ELF {
+public:
+ CSKYToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind) const override;
+ RuntimeLibType GetDefaultRuntimeLibType() const override;
+ UnwindLibType GetUnwindLibType(const llvm::opt::ArgList &Args) const override;
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void
+ addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
+protected:
+ Tool *buildLinker() const override;
+
+private:
+ std::string computeSysRoot() const override;
+};
+
+} // end namespace toolchains
+
+namespace tools {
+namespace CSKY {
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
+public:
+ Linker(const ToolChain &TC) : Tool("CSKY::Linker", "ld", TC) {}
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+} // end namespace CSKY
+} // end namespace tools
+
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CSKYTOOLCHAIN_H
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp
index cb38ab51327c..aa344b3465ab 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp
@@ -10,6 +10,8 @@
#include "AMDGPU.h"
#include "Arch/AArch64.h"
#include "Arch/ARM.h"
+#include "Arch/CSKY.h"
+#include "Arch/LoongArch.h"
#include "Arch/M68k.h"
#include "Arch/Mips.h"
#include "Arch/PPC.h"
@@ -22,29 +24,43 @@
#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/HeaderInclude.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/MakeSupport.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Version.h"
+#include "clang/Config/config.h"
+#include "clang/Driver/Action.h"
#include "clang/Driver/Distro.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
+#include "clang/Driver/Types.h"
#include "clang/Driver/XRayArgs.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/BinaryFormat/Magic.h"
#include "llvm/Config/llvm-config.h"
+#include "llvm/Object/ObjectFile.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Compression.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
-#include "llvm/Support/TargetParser.h"
+#include "llvm/Support/RISCVISAInfo.h"
#include "llvm/Support/YAMLParser.h"
+#include "llvm/TargetParser/ARMTargetParserCommon.h"
+#include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/LoongArchTargetParser.h"
+#include "llvm/TargetParser/RISCVTargetParser.h"
+#include <cctype>
using namespace clang::driver;
using namespace clang::driver::tools;
@@ -52,8 +68,11 @@ using namespace clang;
using namespace llvm::opt;
static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) {
- if (Arg *A =
- Args.getLastArg(clang::driver::options::OPT_C, options::OPT_CC)) {
+ if (Arg *A = Args.getLastArg(clang::driver::options::OPT_C, options::OPT_CC,
+ options::OPT_fminimize_whitespace,
+ options::OPT_fno_minimize_whitespace,
+ options::OPT_fkeep_system_includes,
+ options::OPT_fno_keep_system_includes)) {
if (!Args.hasArg(options::OPT_E) && !Args.hasArg(options::OPT__SLASH_P) &&
!Args.hasArg(options::OPT__SLASH_EP) && !D.CCCIsCPP()) {
D.Diag(clang::diag::err_drv_argument_only_allowed_with)
@@ -90,34 +109,6 @@ static void EscapeSpacesAndBackslashes(const char *Arg,
}
}
-// Quote target names for inclusion in GNU Make dependency files.
-// Only the characters '$', '#', ' ', '\t' are quoted.
-static void QuoteTarget(StringRef Target, SmallVectorImpl<char> &Res) {
- for (unsigned i = 0, e = Target.size(); i != e; ++i) {
- switch (Target[i]) {
- case ' ':
- case '\t':
- // Escape the preceding backslashes
- for (int j = i - 1; j >= 0 && Target[j] == '\\'; --j)
- Res.push_back('\\');
-
- // Escape the space/tab
- Res.push_back('\\');
- break;
- case '$':
- Res.push_back('$');
- break;
- case '#':
- Res.push_back('\\');
- break;
- default:
- break;
- }
-
- Res.push_back(Target[i]);
- }
-}
-
/// Apply \a Work on the current tool chain \a RegularToolChain and any other
/// offloading tool chain that is associated with the current action \a JA.
static void
@@ -220,17 +211,21 @@ static void ParseMRecip(const Driver &D, const ArgList &Args,
llvm::StringMap<bool> OptionStrings;
OptionStrings.insert(std::make_pair("divd", false));
OptionStrings.insert(std::make_pair("divf", false));
+ OptionStrings.insert(std::make_pair("divh", false));
OptionStrings.insert(std::make_pair("vec-divd", false));
OptionStrings.insert(std::make_pair("vec-divf", false));
+ OptionStrings.insert(std::make_pair("vec-divh", false));
OptionStrings.insert(std::make_pair("sqrtd", false));
OptionStrings.insert(std::make_pair("sqrtf", false));
+ OptionStrings.insert(std::make_pair("sqrth", false));
OptionStrings.insert(std::make_pair("vec-sqrtd", false));
OptionStrings.insert(std::make_pair("vec-sqrtf", false));
+ OptionStrings.insert(std::make_pair("vec-sqrth", false));
for (unsigned i = 0; i != NumOptions; ++i) {
StringRef Val = A->getValue(i);
- bool IsDisabled = Val.startswith(DisabledPrefixIn);
+ bool IsDisabled = Val.starts_with(DisabledPrefixIn);
// Ignore the disablement token for string matching.
if (IsDisabled)
Val = Val.substr(1);
@@ -249,10 +244,11 @@ static void ParseMRecip(const Driver &D, const ArgList &Args,
D.Diag(diag::err_drv_unknown_argument) << Val;
return;
}
- // The option was specified without a float or double suffix.
- // Make sure that the double entry was not already specified.
+ // The option was specified without a half or float or double suffix.
+ // Make sure that the double or half entry was not already specified.
// The float entry will be checked below.
- if (OptionStrings[ValBase.str() + 'd']) {
+ if (OptionStrings[ValBase.str() + 'd'] ||
+ OptionStrings[ValBase.str() + 'h']) {
D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Val;
return;
}
@@ -267,9 +263,12 @@ static void ParseMRecip(const Driver &D, const ArgList &Args,
// Mark the matched option as found. Do not allow duplicate specifiers.
OptionIter->second = true;
- // If the precision was not specified, also mark the double entry as found.
- if (ValBase.back() != 'f' && ValBase.back() != 'd')
+ // If the precision was not specified, also mark the double and half entry
+ // as found.
+ if (ValBase.back() != 'f' && ValBase.back() != 'd' && ValBase.back() != 'h') {
OptionStrings[ValBase.str() + 'd'] = true;
+ OptionStrings[ValBase.str() + 'h'] = true;
+ }
// Build the output string.
StringRef Prefix = IsDisabled ? DisabledPrefixOut : EnabledPrefixOut;
@@ -302,87 +301,6 @@ static void ParseMPreferVectorWidth(const Driver &D, const ArgList &Args,
}
}
-static void getWebAssemblyTargetFeatures(const ArgList &Args,
- std::vector<StringRef> &Features) {
- handleTargetFeaturesGroup(Args, Features, options::OPT_m_wasm_Features_Group);
-}
-
-static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
- const ArgList &Args, ArgStringList &CmdArgs,
- bool ForAS, bool IsAux = false) {
- std::vector<StringRef> Features;
- switch (Triple.getArch()) {
- default:
- break;
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- mips::getMIPSTargetFeatures(D, Triple, Args, Features);
- break;
-
- case llvm::Triple::arm:
- case llvm::Triple::armeb:
- case llvm::Triple::thumb:
- case llvm::Triple::thumbeb:
- arm::getARMTargetFeatures(D, Triple, Args, CmdArgs, Features, ForAS);
- break;
-
- case llvm::Triple::ppc:
- case llvm::Triple::ppcle:
- case llvm::Triple::ppc64:
- case llvm::Triple::ppc64le:
- ppc::getPPCTargetFeatures(D, Triple, Args, Features);
- break;
- case llvm::Triple::riscv32:
- case llvm::Triple::riscv64:
- riscv::getRISCVTargetFeatures(D, Triple, Args, Features);
- break;
- case llvm::Triple::systemz:
- systemz::getSystemZTargetFeatures(D, Args, Features);
- break;
- case llvm::Triple::aarch64:
- case llvm::Triple::aarch64_32:
- case llvm::Triple::aarch64_be:
- aarch64::getAArch64TargetFeatures(D, Triple, Args, Features, ForAS);
- break;
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- x86::getX86TargetFeatures(D, Triple, Args, Features);
- break;
- case llvm::Triple::hexagon:
- hexagon::getHexagonTargetFeatures(D, Args, Features);
- break;
- case llvm::Triple::wasm32:
- case llvm::Triple::wasm64:
- getWebAssemblyTargetFeatures(Args, Features);
- break;
- case llvm::Triple::sparc:
- case llvm::Triple::sparcel:
- case llvm::Triple::sparcv9:
- sparc::getSparcTargetFeatures(D, Args, Features);
- break;
- case llvm::Triple::r600:
- case llvm::Triple::amdgcn:
- amdgpu::getAMDGPUTargetFeatures(D, Triple, Args, Features);
- break;
- case llvm::Triple::m68k:
- m68k::getM68kTargetFeatures(D, Triple, Args, Features);
- break;
- case llvm::Triple::msp430:
- msp430::getMSP430TargetFeatures(D, Args, Features);
- break;
- case llvm::Triple::ve:
- ve::getVETargetFeatures(D, Args, Features);
- break;
- }
-
- for (auto Feature : unifyTargetFeatures(Features)) {
- CmdArgs.push_back(IsAux ? "-aux-target-feature" : "-target-feature");
- CmdArgs.push_back(Feature.data());
- }
-}
-
static bool
shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime,
const llvm::Triple &Triple) {
@@ -401,7 +319,7 @@ shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime,
}
/// Adds exception related arguments to the driver command arguments. There's a
-/// master flag, -fexceptions and also language specific flags to enable/disable
+/// main flag, -fexceptions and also language specific flags to enable/disable
/// C++ and Objective-C exceptions. This makes it possible to for example
/// disable C++ exceptions but enable Objective-C exceptions.
static bool addExceptionArgs(const ArgList &Args, types::ID InputType,
@@ -446,9 +364,9 @@ static bool addExceptionArgs(const ArgList &Args, types::ID InputType,
}
if (types::isCXX(InputType)) {
- // Disable C++ EH by default on XCore and PS4.
- bool CXXExceptionsEnabled =
- Triple.getArch() != llvm::Triple::xcore && !Triple.isPS4CPU();
+ // Disable C++ EH by default on XCore and PS4/PS5.
+ bool CXXExceptionsEnabled = Triple.getArch() != llvm::Triple::xcore &&
+ !Triple.isPS() && !Triple.isDriverKit();
Arg *ExceptionArg = Args.getLastArg(
options::OPT_fcxx_exceptions, options::OPT_fno_cxx_exceptions,
options::OPT_fexceptions, options::OPT_fno_exceptions);
@@ -469,6 +387,9 @@ static bool addExceptionArgs(const ArgList &Args, types::ID InputType,
// So we do not set EH to false.
Args.AddLastArg(CmdArgs, options::OPT_fignore_exceptions);
+ Args.addOptInFlag(CmdArgs, options::OPT_fassume_nothrow_exception_dtor,
+ options::OPT_fno_assume_nothrow_exception_dtor);
+
if (EH)
CmdArgs.push_back("-fexceptions");
return EH;
@@ -490,140 +411,10 @@ static bool ShouldEnableAutolink(const ArgList &Args, const ToolChain &TC,
Default);
}
-// Convert an arg of the form "-gN" or "-ggdbN" or one of their aliases
-// to the corresponding DebugInfoKind.
-static codegenoptions::DebugInfoKind DebugLevelToInfoKind(const Arg &A) {
- assert(A.getOption().matches(options::OPT_gN_Group) &&
- "Not a -g option that specifies a debug-info level");
- if (A.getOption().matches(options::OPT_g0) ||
- A.getOption().matches(options::OPT_ggdb0))
- return codegenoptions::NoDebugInfo;
- if (A.getOption().matches(options::OPT_gline_tables_only) ||
- A.getOption().matches(options::OPT_ggdb1))
- return codegenoptions::DebugLineTablesOnly;
- if (A.getOption().matches(options::OPT_gline_directives_only))
- return codegenoptions::DebugDirectivesOnly;
- return codegenoptions::DebugInfoConstructor;
-}
-
-static bool mustUseNonLeafFramePointerForTarget(const llvm::Triple &Triple) {
- switch (Triple.getArch()){
- default:
- return false;
- case llvm::Triple::arm:
- case llvm::Triple::thumb:
- // ARM Darwin targets require a frame pointer to be always present to aid
- // offline debugging via backtraces.
- return Triple.isOSDarwin();
- }
-}
-
-static bool useFramePointerForTargetByDefault(const ArgList &Args,
- const llvm::Triple &Triple) {
- if (Args.hasArg(options::OPT_pg) && !Args.hasArg(options::OPT_mfentry))
- return true;
-
- switch (Triple.getArch()) {
- case llvm::Triple::xcore:
- case llvm::Triple::wasm32:
- case llvm::Triple::wasm64:
- case llvm::Triple::msp430:
- // XCore never wants frame pointers, regardless of OS.
- // WebAssembly never wants frame pointers.
- return false;
- case llvm::Triple::ppc:
- case llvm::Triple::ppcle:
- case llvm::Triple::ppc64:
- case llvm::Triple::ppc64le:
- case llvm::Triple::riscv32:
- case llvm::Triple::riscv64:
- case llvm::Triple::amdgcn:
- case llvm::Triple::r600:
- return !areOptimizationsEnabled(Args);
- default:
- break;
- }
-
- if (Triple.isOSNetBSD()) {
- return !areOptimizationsEnabled(Args);
- }
-
- if (Triple.isOSLinux() || Triple.getOS() == llvm::Triple::CloudABI ||
- Triple.isOSHurd()) {
- switch (Triple.getArch()) {
- // Don't use a frame pointer on linux if optimizing for certain targets.
- case llvm::Triple::arm:
- case llvm::Triple::armeb:
- case llvm::Triple::thumb:
- case llvm::Triple::thumbeb:
- if (Triple.isAndroid())
- return true;
- LLVM_FALLTHROUGH;
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::systemz:
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- return !areOptimizationsEnabled(Args);
- default:
- return true;
- }
- }
-
- if (Triple.isOSWindows()) {
- switch (Triple.getArch()) {
- case llvm::Triple::x86:
- return !areOptimizationsEnabled(Args);
- case llvm::Triple::x86_64:
- return Triple.isOSBinFormatMachO();
- case llvm::Triple::arm:
- case llvm::Triple::thumb:
- // Windows on ARM builds with FPO disabled to aid fast stack walking
- return true;
- default:
- // All other supported Windows ISAs use xdata unwind information, so frame
- // pointers are not generally useful.
- return false;
- }
- }
-
- return true;
-}
-
-static CodeGenOptions::FramePointerKind
-getFramePointerKind(const ArgList &Args, const llvm::Triple &Triple) {
- // We have 4 states:
- //
- // 00) leaf retained, non-leaf retained
- // 01) leaf retained, non-leaf omitted (this is invalid)
- // 10) leaf omitted, non-leaf retained
- // (what -momit-leaf-frame-pointer was designed for)
- // 11) leaf omitted, non-leaf omitted
- //
- // "omit" options taking precedence over "no-omit" options is the only way
- // to make 3 valid states representable
- Arg *A = Args.getLastArg(options::OPT_fomit_frame_pointer,
- options::OPT_fno_omit_frame_pointer);
- bool OmitFP = A && A->getOption().matches(options::OPT_fomit_frame_pointer);
- bool NoOmitFP =
- A && A->getOption().matches(options::OPT_fno_omit_frame_pointer);
- bool OmitLeafFP = Args.hasFlag(options::OPT_momit_leaf_frame_pointer,
- options::OPT_mno_omit_leaf_frame_pointer,
- Triple.isAArch64() || Triple.isPS4CPU());
- if (NoOmitFP || mustUseNonLeafFramePointerForTarget(Triple) ||
- (!OmitFP && useFramePointerForTargetByDefault(Args, Triple))) {
- if (OmitLeafFP)
- return CodeGenOptions::FramePointerKind::NonLeaf;
- return CodeGenOptions::FramePointerKind::All;
- }
- return CodeGenOptions::FramePointerKind::None;
-}
-
/// Add a CC1 option to specify the debug compilation directory.
-static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs,
- const llvm::vfs::FileSystem &VFS) {
+static const char *addDebugCompDirArg(const ArgList &Args,
+ ArgStringList &CmdArgs,
+ const llvm::vfs::FileSystem &VFS) {
if (Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ,
options::OPT_fdebug_compilation_dir_EQ)) {
if (A->getOption().matches(options::OPT_ffile_compilation_dir_EQ))
@@ -635,20 +426,62 @@ static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs,
VFS.getCurrentWorkingDirectory()) {
CmdArgs.push_back(Args.MakeArgString("-fdebug-compilation-dir=" + *CWD));
}
+ StringRef Path(CmdArgs.back());
+ return Path.substr(Path.find('=') + 1).data();
+}
+
+static void addDebugObjectName(const ArgList &Args, ArgStringList &CmdArgs,
+ const char *DebugCompilationDir,
+ const char *OutputFileName) {
+ // No need to generate a value for -object-file-name if it was provided.
+ for (auto *Arg : Args.filtered(options::OPT_Xclang))
+ if (StringRef(Arg->getValue()).starts_with("-object-file-name"))
+ return;
+
+ if (Args.hasArg(options::OPT_object_file_name_EQ))
+ return;
+
+ SmallString<128> ObjFileNameForDebug(OutputFileName);
+ if (ObjFileNameForDebug != "-" &&
+ !llvm::sys::path::is_absolute(ObjFileNameForDebug) &&
+ (!DebugCompilationDir ||
+ llvm::sys::path::is_absolute(DebugCompilationDir))) {
+ // Make the path absolute in the debug infos like MSVC does.
+ llvm::sys::fs::make_absolute(ObjFileNameForDebug);
+ }
+ // If the object file name is a relative path, then always use Windows
+ // backslash style as -object-file-name is used for embedding object file path
+ // in codeview and it can only be generated when targeting on Windows.
+ // Otherwise, just use native absolute path.
+ llvm::sys::path::Style Style =
+ llvm::sys::path::is_absolute(ObjFileNameForDebug)
+ ? llvm::sys::path::Style::native
+ : llvm::sys::path::Style::windows_backslash;
+ llvm::sys::path::remove_dots(ObjFileNameForDebug, /*remove_dot_dot=*/true,
+ Style);
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-object-file-name=") + ObjFileNameForDebug));
}
/// Add a CC1 and CC1AS option to specify the debug file path prefix map.
-static void addDebugPrefixMapArg(const Driver &D, const ArgList &Args, ArgStringList &CmdArgs) {
- for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ,
- options::OPT_fdebug_prefix_map_EQ)) {
- StringRef Map = A->getValue();
- if (Map.find('=') == StringRef::npos)
- D.Diag(diag::err_drv_invalid_argument_to_option)
- << Map << A->getOption().getName();
+static void addDebugPrefixMapArg(const Driver &D, const ToolChain &TC,
+ const ArgList &Args, ArgStringList &CmdArgs) {
+ auto AddOneArg = [&](StringRef Map, StringRef Name) {
+ if (!Map.contains('='))
+ D.Diag(diag::err_drv_invalid_argument_to_option) << Map << Name;
else
CmdArgs.push_back(Args.MakeArgString("-fdebug-prefix-map=" + Map));
+ };
+
+ for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ,
+ options::OPT_fdebug_prefix_map_EQ)) {
+ AddOneArg(A->getValue(), A->getOption().getName());
A->claim();
}
+ std::string GlobalRemapEntry = TC.GetGlobalDebugPathRemapping();
+ if (GlobalRemapEntry.empty())
+ return;
+ AddOneArg(GlobalRemapEntry, "environment");
}
/// Add a CC1 and CC1AS option to specify the macro file path prefix map.
@@ -657,7 +490,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
@@ -672,7 +505,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
@@ -746,10 +579,10 @@ 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 JobAction &JA, const InputInfo &Output,
+ const ArgList &Args, SanitizerArgs &SanArgs,
ArgStringList &CmdArgs) {
-
+ const Driver &D = TC.getDriver();
auto *PGOGenerateArg = Args.getLastArg(options::OPT_fprofile_generate,
options::OPT_fprofile_generate_EQ,
options::OPT_fno_profile_generate);
@@ -757,12 +590,7 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C,
PGOGenerateArg->getOption().matches(options::OPT_fno_profile_generate))
PGOGenerateArg = nullptr;
- auto *CSPGOGenerateArg = Args.getLastArg(options::OPT_fcs_profile_generate,
- options::OPT_fcs_profile_generate_EQ,
- options::OPT_fno_profile_generate);
- if (CSPGOGenerateArg &&
- CSPGOGenerateArg->getOption().matches(options::OPT_fno_profile_generate))
- CSPGOGenerateArg = nullptr;
+ auto *CSPGOGenerateArg = getLastCSProfileGenerateArg(Args);
auto *ProfileGenerateArg = Args.getLastArg(
options::OPT_fprofile_instr_generate,
@@ -794,14 +622,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();
if (Arg *ProfileSampleUseArg = getLastProfileSampleUseArg(Args))
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< ProfileSampleUseArg->getSpelling() << TC.getTriple().str();
@@ -869,10 +689,6 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C,
options::OPT_fno_test_coverage, false) ||
Args.hasArg(options::OPT_coverage);
bool EmitCovData = TC.needsGCovInstrumentation(Args);
- if (EmitCovNotes)
- CmdArgs.push_back("-ftest-coverage");
- if (EmitCovData)
- CmdArgs.push_back("-fprofile-arcs");
if (Args.hasFlag(options::OPT_fcoverage_mapping,
options::OPT_fno_coverage_mapping, false)) {
@@ -884,6 +700,17 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C,
CmdArgs.push_back("-fcoverage-mapping");
}
+ if (Args.hasFlag(options::OPT_fmcdc_coverage, options::OPT_fno_mcdc_coverage,
+ false)) {
+ if (!Args.hasFlag(options::OPT_fcoverage_mapping,
+ options::OPT_fno_coverage_mapping, false))
+ D.Diag(clang::diag::err_drv_argument_only_allowed_with)
+ << "-fcoverage-mcdc"
+ << "-fcoverage-mapping";
+
+ CmdArgs.push_back("-fcoverage-mcdc");
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ,
options::OPT_fcoverage_compilation_dir_EQ)) {
if (A->getOption().matches(options::OPT_ffile_compilation_dir_EQ))
@@ -925,11 +752,30 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C,
CmdArgs.push_back("-fprofile-update=atomic");
else if (Val != "single")
D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << Val;
- } else if (TC.getSanitizerArgs().needsTsanRt()) {
- CmdArgs.push_back("-fprofile-update=atomic");
+ << A->getSpelling() << Val;
}
+ int FunctionGroups = 1;
+ int SelectedFunctionGroup = 0;
+ if (const auto *A = Args.getLastArg(options::OPT_fprofile_function_groups)) {
+ StringRef Val = A->getValue();
+ if (Val.getAsInteger(0, FunctionGroups) || FunctionGroups < 1)
+ D.Diag(diag::err_drv_invalid_int_value) << A->getAsString(Args) << Val;
+ }
+ if (const auto *A =
+ Args.getLastArg(options::OPT_fprofile_selected_function_group)) {
+ StringRef Val = A->getValue();
+ if (Val.getAsInteger(0, SelectedFunctionGroup) ||
+ SelectedFunctionGroup < 0 || SelectedFunctionGroup >= FunctionGroups)
+ D.Diag(diag::err_drv_invalid_int_value) << A->getAsString(Args) << Val;
+ }
+ if (FunctionGroups != 1)
+ CmdArgs.push_back(Args.MakeArgString("-fprofile-function-groups=" +
+ Twine(FunctionGroups)));
+ if (SelectedFunctionGroup != 0)
+ CmdArgs.push_back(Args.MakeArgString("-fprofile-selected-function-group=" +
+ Twine(SelectedFunctionGroup)));
+
// Leave -fprofile-dir= an unused argument unless .gcda emission is
// enabled. To be polite, with '-fprofile-arcs -fno-profile-arcs' consider
// the flag used. There is no -fno-profile-dir, so the user has no
@@ -939,36 +785,45 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C,
Args.hasArg(options::OPT_coverage))
FProfileDir = Args.getLastArg(options::OPT_fprofile_dir);
- // Put the .gcno and .gcda files (if needed) next to the object file or
- // bitcode file in the case of LTO.
- // FIXME: There should be a simpler way to find the object file for this
- // input, and this code probably does the wrong thing for commands that
- // compile and link all at once.
- if ((Args.hasArg(options::OPT_c) || Args.hasArg(options::OPT_S)) &&
- (EmitCovNotes || EmitCovData) && Output.isFilename()) {
- SmallString<128> OutputFilename;
- if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT__SLASH_Fo))
- OutputFilename = FinalOutput->getValue();
- else if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o))
- OutputFilename = FinalOutput->getValue();
- else
- OutputFilename = llvm::sys::path::filename(Output.getBaseInput());
- SmallString<128> CoverageFilename = OutputFilename;
+ // TODO: Don't claim -c/-S to warn about -fsyntax-only -c/-S, -E -c/-S,
+ // like we warn about -fsyntax-only -E.
+ (void)(Args.hasArg(options::OPT_c) || Args.hasArg(options::OPT_S));
+
+ // Put the .gcno and .gcda files (if needed) next to the primary output file,
+ // or fall back to a file in the current directory for `clang -c --coverage
+ // d/a.c` in the absence of -o.
+ if (EmitCovNotes || EmitCovData) {
+ SmallString<128> CoverageFilename;
+ if (Arg *DumpDir = Args.getLastArgNoClaim(options::OPT_dumpdir)) {
+ // Form ${dumpdir}${basename}.gcno. Note that dumpdir may not end with a
+ // path separator.
+ CoverageFilename = DumpDir->getValue();
+ CoverageFilename += llvm::sys::path::filename(Output.getBaseInput());
+ } else if (Arg *FinalOutput =
+ C.getArgs().getLastArg(options::OPT__SLASH_Fo)) {
+ CoverageFilename = FinalOutput->getValue();
+ } else if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o)) {
+ CoverageFilename = FinalOutput->getValue();
+ } else {
+ CoverageFilename = llvm::sys::path::filename(Output.getBaseInput());
+ }
if (llvm::sys::path::is_relative(CoverageFilename))
(void)D.getVFS().makeAbsolute(CoverageFilename);
llvm::sys::path::replace_extension(CoverageFilename, "gcno");
-
- CmdArgs.push_back("-coverage-notes-file");
- CmdArgs.push_back(Args.MakeArgString(CoverageFilename));
+ if (EmitCovNotes) {
+ CmdArgs.push_back(
+ Args.MakeArgString("-coverage-notes-file=" + CoverageFilename));
+ }
if (EmitCovData) {
if (FProfileDir) {
+ SmallString<128> Gcno = std::move(CoverageFilename);
CoverageFilename = FProfileDir->getValue();
- llvm::sys::path::append(CoverageFilename, OutputFilename);
+ llvm::sys::path::append(CoverageFilename, Gcno);
}
llvm::sys::path::replace_extension(CoverageFilename, "gcda");
- CmdArgs.push_back("-coverage-data-file");
- CmdArgs.push_back(Args.MakeArgString(CoverageFilename));
+ CmdArgs.push_back(
+ Args.MakeArgString("-coverage-data-file=" + CoverageFilename));
}
}
}
@@ -978,11 +833,7 @@ static bool ContainsCompileAction(const Action *A) {
if (isa<CompileJobAction>(A) || isa<BackendJobAction>(A))
return true;
- for (const auto &AI : A->inputs())
- if (ContainsCompileAction(AI))
- return true;
-
- return false;
+ return llvm::any_of(A->inputs(), ContainsCompileAction);
}
/// Check if -relax-all should be passed to the internal assembler.
@@ -1007,52 +858,12 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) {
RelaxDefault);
}
-// Extract the integer N from a string spelled "-dwarf-N", returning 0
-// on mismatch. The StringRef input (rather than an Arg) allows
-// for use by the "-Xassembler" option parser.
-static unsigned DwarfVersionNum(StringRef ArgValue) {
- return llvm::StringSwitch<unsigned>(ArgValue)
- .Case("-gdwarf-2", 2)
- .Case("-gdwarf-3", 3)
- .Case("-gdwarf-4", 4)
- .Case("-gdwarf-5", 5)
- .Default(0);
-}
-
-// Find a DWARF format version option.
-// This function is a complementary for DwarfVersionNum().
-static const Arg *getDwarfNArg(const ArgList &Args) {
- return Args.getLastArg(options::OPT_gdwarf_2, options::OPT_gdwarf_3,
- options::OPT_gdwarf_4, options::OPT_gdwarf_5,
- options::OPT_gdwarf);
-}
-
-static void RenderDebugEnablingArgs(const ArgList &Args, ArgStringList &CmdArgs,
- codegenoptions::DebugInfoKind DebugInfoKind,
- unsigned DwarfVersion,
- llvm::DebuggerKind DebuggerTuning) {
- switch (DebugInfoKind) {
- case codegenoptions::DebugDirectivesOnly:
- CmdArgs.push_back("-debug-info-kind=line-directives-only");
- break;
- case codegenoptions::DebugLineTablesOnly:
- CmdArgs.push_back("-debug-info-kind=line-tables-only");
- break;
- case codegenoptions::DebugInfoConstructor:
- CmdArgs.push_back("-debug-info-kind=constructor");
- break;
- case codegenoptions::LimitedDebugInfo:
- CmdArgs.push_back("-debug-info-kind=limited");
- break;
- case codegenoptions::FullDebugInfo:
- CmdArgs.push_back("-debug-info-kind=standalone");
- break;
- case codegenoptions::UnusedTypeInfo:
- CmdArgs.push_back("-debug-info-kind=unused-types");
- break;
- default:
- break;
- }
+static void
+RenderDebugEnablingArgs(const ArgList &Args, ArgStringList &CmdArgs,
+ llvm::codegenoptions::DebugInfoKind DebugInfoKind,
+ unsigned DwarfVersion,
+ llvm::DebuggerKind DebuggerTuning) {
+ addDebugInfoKind(CmdArgs, DebugInfoKind);
if (DwarfVersion > 0)
CmdArgs.push_back(
Args.MakeArgString("-dwarf-version=" + Twine(DwarfVersion)));
@@ -1095,40 +906,31 @@ static void RenderDebugInfoCompressionArgs(const ArgList &Args,
StringRef Value = A->getValue();
if (Value == "none") {
CmdArgs.push_back("--compress-debug-sections=none");
- } else if (Value == "zlib" || Value == "zlib-gnu") {
- if (llvm::zlib::isAvailable()) {
+ } else if (Value == "zlib") {
+ if (llvm::compression::zlib::isAvailable()) {
+ CmdArgs.push_back(
+ Args.MakeArgString("--compress-debug-sections=" + Twine(Value)));
+ } else {
+ D.Diag(diag::warn_debug_compression_unavailable) << "zlib";
+ }
+ } else if (Value == "zstd") {
+ if (llvm::compression::zstd::isAvailable()) {
CmdArgs.push_back(
Args.MakeArgString("--compress-debug-sections=" + Twine(Value)));
} else {
- D.Diag(diag::warn_debug_compression_unavailable);
+ D.Diag(diag::warn_debug_compression_unavailable) << "zstd";
}
} else {
D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << Value;
+ << A->getSpelling() << Value;
}
}
}
-static const char *RelocationModelName(llvm::Reloc::Model Model) {
- switch (Model) {
- case llvm::Reloc::Static:
- return "static";
- case llvm::Reloc::PIC_:
- return "pic";
- case llvm::Reloc::DynamicNoPIC:
- return "dynamic-no-pic";
- case llvm::Reloc::ROPI:
- return "ropi";
- case llvm::Reloc::RWPI:
- return "rwpi";
- case llvm::Reloc::ROPI_RWPI:
- return "ropi-rwpi";
- }
- llvm_unreachable("Unknown Reloc::Model kind");
-}
static void handleAMDGPUCodeObjectVersionOptions(const Driver &D,
const ArgList &Args,
- ArgStringList &CmdArgs) {
+ ArgStringList &CmdArgs,
+ bool IsCC1As = false) {
// If no version was requested by the user, use the default value from the
// back end. This is consistent with the value returned from
// getAMDGPUCodeObjectVersion. This lets clang emit IR for amdgpu without
@@ -1140,9 +942,53 @@ static void handleAMDGPUCodeObjectVersionOptions(const Driver &D,
Args.MakeArgString(Twine("--amdhsa-code-object-version=") +
Twine(CodeObjVer)));
CmdArgs.insert(CmdArgs.begin() + 1, "-mllvm");
+ // -cc1as does not accept -mcode-object-version option.
+ if (!IsCC1As)
+ CmdArgs.insert(CmdArgs.begin() + 1,
+ Args.MakeArgString(Twine("-mcode-object-version=") +
+ Twine(CodeObjVer)));
}
}
+static bool maybeHasClangPchSignature(const Driver &D, StringRef Path) {
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MemBuf =
+ D.getVFS().getBufferForFile(Path);
+ if (!MemBuf)
+ return false;
+ llvm::file_magic Magic = llvm::identify_magic((*MemBuf)->getBuffer());
+ if (Magic == llvm::file_magic::unknown)
+ return false;
+ // Return true for both raw Clang AST files and object files which may
+ // contain a __clangast section.
+ if (Magic == llvm::file_magic::clang_ast)
+ return true;
+ Expected<std::unique_ptr<llvm::object::ObjectFile>> Obj =
+ llvm::object::ObjectFile::createObjectFile(**MemBuf, Magic);
+ return !Obj.takeError();
+}
+
+static bool gchProbe(const Driver &D, StringRef Path) {
+ llvm::ErrorOr<llvm::vfs::Status> Status = D.getVFS().status(Path);
+ if (!Status)
+ return false;
+
+ if (Status->isDirectory()) {
+ std::error_code EC;
+ for (llvm::vfs::directory_iterator DI = D.getVFS().dir_begin(Path, EC), DE;
+ !EC && DI != DE; DI = DI.increment(EC)) {
+ if (maybeHasClangPchSignature(D, DI->path()))
+ return true;
+ }
+ D.Diag(diag::warn_drv_pch_ignoring_gch_dir) << Path;
+ return false;
+ }
+
+ if (maybeHasClangPchSignature(D, Path))
+ return true;
+ D.Diag(diag::warn_drv_pch_ignoring_gch_file) << Path;
+ return false;
+}
+
void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
const Driver &D, const ArgList &Args,
ArgStringList &CmdArgs,
@@ -1195,7 +1041,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
} else {
CmdArgs.push_back("-MT");
SmallString<128> Quoted;
- QuoteTarget(A->getValue(), Quoted);
+ quoteMakeTarget(A->getValue(), Quoted);
CmdArgs.push_back(Args.MakeArgString(Quoted));
}
}
@@ -1220,7 +1066,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-MT");
SmallString<128> Quoted;
- QuoteTarget(DepTarget, Quoted);
+ quoteMakeTarget(DepTarget, Quoted);
CmdArgs.push_back(Args.MakeArgString(Quoted));
}
@@ -1252,9 +1098,38 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
if (JA.isOffloading(Action::OFK_HIP))
getToolChain().AddHIPIncludeArgs(Args, CmdArgs);
+ // If we are compiling for a GPU target we want to override the system headers
+ // with ones created by the 'libc' project if present.
+ if (!Args.hasArg(options::OPT_nostdinc) &&
+ !Args.hasArg(options::OPT_nogpuinc) &&
+ !Args.hasArg(options::OPT_nobuiltininc)) {
+ // Without an offloading language we will include these headers directly.
+ // Offloading languages will instead only use the declarations stored in
+ // the resource directory at clang/lib/Headers/llvm_libc_wrappers.
+ if ((getToolChain().getTriple().isNVPTX() ||
+ getToolChain().getTriple().isAMDGCN()) &&
+ C.getActiveOffloadKinds() == Action::OFK_None) {
+ SmallString<128> P(llvm::sys::path::parent_path(D.InstalledDir));
+ llvm::sys::path::append(P, "include");
+ llvm::sys::path::append(P, "gpu-none-llvm");
+ CmdArgs.push_back("-c-isystem");
+ CmdArgs.push_back(Args.MakeArgString(P));
+ } else if (C.getActiveOffloadKinds() == Action::OFK_OpenMP) {
+ // TODO: CUDA / HIP include their own headers for some common functions
+ // implemented here. We'll need to clean those up so they do not conflict.
+ SmallString<128> P(D.ResourceDir);
+ llvm::sys::path::append(P, "include");
+ llvm::sys::path::append(P, "llvm_libc_wrappers");
+ CmdArgs.push_back("-internal-isystem");
+ CmdArgs.push_back(Args.MakeArgString(P));
+ }
+ }
+
// If we are offloading to a target via OpenMP we need to include the
// openmp_wrappers folder which contains alternative system headers.
if (JA.isDeviceOffloading(Action::OFK_OpenMP) &&
+ !Args.hasArg(options::OPT_nostdinc) &&
+ !Args.hasArg(options::OPT_nogpuinc) &&
(getToolChain().getTriple().isNVPTX() ||
getToolChain().getTriple().isAMDGCN())) {
if (!Args.hasArg(options::OPT_nobuiltininc)) {
@@ -1311,7 +1186,8 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
bool RenderedImplicitInclude = false;
for (const Arg *A : Args.filtered(options::OPT_clang_i_Group)) {
- if (A->getOption().matches(options::OPT_include)) {
+ if (A->getOption().matches(options::OPT_include) &&
+ D.getProbePrecompiled()) {
// Handling of gcc-style gch precompiled headers.
bool IsFirstImplicitInclude = !RenderedImplicitInclude;
RenderedImplicitInclude = true;
@@ -1322,14 +1198,13 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
// so that replace_extension does the right thing.
P += ".dummy";
llvm::sys::path::replace_extension(P, "pch");
- if (llvm::sys::fs::exists(P))
+ if (D.getVFS().exists(P))
FoundPCH = true;
if (!FoundPCH) {
+ // For GCC compat, probe for a file or directory ending in .gch instead.
llvm::sys::path::replace_extension(P, "gch");
- if (llvm::sys::fs::exists(P)) {
- FoundPCH = true;
- }
+ FoundPCH = gchProbe(D, P.str());
}
if (FoundPCH) {
@@ -1354,6 +1229,9 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
} else if (A->getOption().matches(options::OPT_stdlibxx_isystem)) {
// Translated to -internal-isystem by the driver, no need to pass to cc1.
continue;
+ } else if (A->getOption().matches(options::OPT_ibuiltininc)) {
+ // This is used only by the driver. No need to pass to cc1.
+ continue;
}
// Not translated, render as usual.
@@ -1361,7 +1239,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
A->render(Args, CmdArgs);
}
- Args.AddAllArgs(CmdArgs,
+ Args.addAllArgs(CmdArgs,
{options::OPT_D, options::OPT_U, options::OPT_I_Group,
options::OPT_F, options::OPT_index_header_map});
@@ -1431,6 +1309,17 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
addMacroPrefixMapArg(D, Args, CmdArgs);
addCoveragePrefixMapArg(D, Args, CmdArgs);
+
+ Args.AddLastArg(CmdArgs, options::OPT_ffile_reproducible,
+ options::OPT_fno_file_reproducible);
+
+ if (const char *Epoch = std::getenv("SOURCE_DATE_EPOCH")) {
+ CmdArgs.push_back("-source-date-epoch");
+ CmdArgs.push_back(Args.MakeArgString(Epoch));
+ }
+
+ Args.addOptInFlag(CmdArgs, options::OPT_fdefine_target_os_macros,
+ options::OPT_fno_define_target_os_macros);
}
// FIXME: Move to target hook.
@@ -1587,8 +1476,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,18 +1485,85 @@ 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();
}
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName);
}
+
+void AddUnalignedAccessWarning(ArgStringList &CmdArgs) {
+ auto StrictAlignIter =
+ llvm::find_if(llvm::reverse(CmdArgs), [](StringRef Arg) {
+ return Arg == "+strict-align" || Arg == "-strict-align";
+ });
+ if (StrictAlignIter != CmdArgs.rend() &&
+ StringRef(*StrictAlignIter) == "+strict-align")
+ CmdArgs.push_back("-Wunaligned-access");
+}
+}
+
+static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs, bool isAArch64) {
+ const Arg *A = isAArch64
+ ? Args.getLastArg(options::OPT_msign_return_address_EQ,
+ options::OPT_mbranch_protection_EQ)
+ : Args.getLastArg(options::OPT_mbranch_protection_EQ);
+ if (!A)
+ return;
+
+ const Driver &D = TC.getDriver();
+ const llvm::Triple &Triple = TC.getEffectiveTriple();
+ if (!(isAArch64 || (Triple.isArmT32() && Triple.isArmMClass())))
+ D.Diag(diag::warn_incompatible_branch_protection_option)
+ << Triple.getArchName();
+
+ StringRef Scope, Key;
+ bool IndirectBranches, BranchProtectionPAuthLR, GuardedControlStack;
+
+ if (A->getOption().matches(options::OPT_msign_return_address_EQ)) {
+ Scope = A->getValue();
+ if (Scope != "none" && Scope != "non-leaf" && Scope != "all")
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getSpelling() << Scope;
+ Key = "a_key";
+ IndirectBranches = false;
+ BranchProtectionPAuthLR = false;
+ GuardedControlStack = false;
+ } else {
+ StringRef DiagMsg;
+ llvm::ARM::ParsedBranchProtection PBP;
+ if (!llvm::ARM::parseBranchProtection(A->getValue(), PBP, DiagMsg))
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getSpelling() << DiagMsg;
+ if (!isAArch64 && PBP.Key == "b_key")
+ D.Diag(diag::warn_unsupported_branch_protection)
+ << "b-key" << A->getAsString(Args);
+ Scope = PBP.Scope;
+ Key = PBP.Key;
+ BranchProtectionPAuthLR = PBP.BranchProtectionPAuthLR;
+ IndirectBranches = PBP.BranchTargetEnforcement;
+ GuardedControlStack = PBP.GuardedControlStack;
+ }
+
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-msign-return-address=") + Scope));
+ if (!Scope.equals("none"))
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-msign-return-address-key=") + Key));
+ if (BranchProtectionPAuthLR)
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-mbranch-protection-pauth-lr")));
+ if (IndirectBranches)
+ CmdArgs.push_back("-mbranch-target-enforce");
+ if (GuardedControlStack)
+ CmdArgs.push_back("-mguarded-control-stack");
}
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);
@@ -1646,6 +1602,11 @@ void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args,
CmdArgs.push_back("-mcmse");
AddAAPCSVolatileBitfieldArgs(Args, CmdArgs);
+
+ // Enable/disable return address signing and indirect branch targets.
+ CollectARMPACBTIOptions(getToolChain(), Args, CmdArgs, false /*isAArch64*/);
+
+ AddUnalignedAccessWarning(CmdArgs);
}
void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple,
@@ -1667,14 +1628,17 @@ void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple,
case llvm::Triple::thumbeb:
// Use the effective triple, which takes into account the deployment target.
AddARMTargetArgs(EffectiveTriple, Args, CmdArgs, KernelOrKext);
- CmdArgs.push_back("-fallow-half-arguments-and-returns");
break;
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_32:
case llvm::Triple::aarch64_be:
AddAArch64TargetArgs(Args, CmdArgs);
- CmdArgs.push_back("-fallow-half-arguments-and-returns");
+ break;
+
+ case llvm::Triple::loongarch32:
+ case llvm::Triple::loongarch64:
+ AddLoongArchTargetArgs(Args, CmdArgs);
break;
case llvm::Triple::mips:
@@ -1761,19 +1725,6 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
RenderAArch64ABI(Triple, Args, CmdArgs);
- if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a53_835769,
- options::OPT_mno_fix_cortex_a53_835769)) {
- CmdArgs.push_back("-mllvm");
- if (A->getOption().matches(options::OPT_mfix_cortex_a53_835769))
- CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=1");
- else
- CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=0");
- } else if (Triple.isAndroid()) {
- // Enabled A53 errata (835769) workaround by default on android
- CmdArgs.push_back("-mllvm");
- CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=1");
- }
-
// Forward the -mglobal-merge option for explicit control over the pass.
if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge,
options::OPT_mno_global_merge)) {
@@ -1785,57 +1736,66 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
}
// Enable/disable return address signing and indirect branch targets.
- if (Arg *A = Args.getLastArg(options::OPT_msign_return_address_EQ,
- options::OPT_mbranch_protection_EQ)) {
-
- const Driver &D = getToolChain().getDriver();
-
- StringRef Scope, Key;
- bool IndirectBranches;
-
- if (A->getOption().matches(options::OPT_msign_return_address_EQ)) {
- Scope = A->getValue();
- if (!Scope.equals("none") && !Scope.equals("non-leaf") &&
- !Scope.equals("all"))
- D.Diag(diag::err_invalid_branch_protection)
- << Scope << A->getAsString(Args);
- Key = "a_key";
- IndirectBranches = false;
- } else {
- StringRef Err;
- llvm::AArch64::ParsedBranchProtection PBP;
- if (!llvm::AArch64::parseBranchProtection(A->getValue(), PBP, Err))
- D.Diag(diag::err_invalid_branch_protection)
- << Err << A->getAsString(Args);
- Scope = PBP.Scope;
- Key = PBP.Key;
- IndirectBranches = PBP.BranchTargetEnforcement;
- }
-
- CmdArgs.push_back(
- Args.MakeArgString(Twine("-msign-return-address=") + Scope));
- CmdArgs.push_back(
- Args.MakeArgString(Twine("-msign-return-address-key=") + Key));
- if (IndirectBranches)
- CmdArgs.push_back("-mbranch-target-enforce");
- }
+ CollectARMPACBTIOptions(getToolChain(), Args, CmdArgs, true /*isAArch64*/);
// Handle -msve_vector_bits=<bits>
if (Arg *A = Args.getLastArg(options::OPT_msve_vector_bits_EQ)) {
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.ends_with("+"))
+ 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;
+ << A->getSpelling() << Val;
}
AddAAPCSVolatileBitfieldArgs(Args, CmdArgs);
+
+ if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)) {
+ CmdArgs.push_back("-tune-cpu");
+ if (strcmp(A->getValue(), "native") == 0)
+ CmdArgs.push_back(Args.MakeArgString(llvm::sys::getHostCPUName()));
+ else
+ CmdArgs.push_back(A->getValue());
+ }
+
+ AddUnalignedAccessWarning(CmdArgs);
+}
+
+void Clang::AddLoongArchTargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ const llvm::Triple &Triple = getToolChain().getTriple();
+
+ CmdArgs.push_back("-target-abi");
+ CmdArgs.push_back(
+ loongarch::getLoongArchABI(getToolChain().getDriver(), Args, Triple)
+ .data());
+
+ // Handle -mtune.
+ if (const Arg *A = Args.getLastArg(options::OPT_mtune_EQ)) {
+ std::string TuneCPU = A->getValue();
+ TuneCPU = loongarch::postProcessTargetCPUString(TuneCPU, Triple);
+ CmdArgs.push_back("-tune-cpu");
+ CmdArgs.push_back(Args.MakeArgString(TuneCPU));
+ }
}
void Clang::AddMIPSTargetArgs(const ArgList &Args,
@@ -1878,6 +1838,11 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,
}
}
+ if (Args.getLastArg(options::OPT_mfix4300)) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-mfix4300");
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_G)) {
StringRef v = A->getValue();
CmdArgs.push_back("-mllvm");
@@ -1967,7 +1932,7 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,
CmdArgs.push_back(Args.MakeArgString("-mips-compact-branches=" + Val));
} else
D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << Val;
+ << A->getSpelling() << Val;
} else
D.Diag(diag::warn_target_unsupported_compact_branches) << CPUName;
}
@@ -1983,14 +1948,20 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,
void Clang::AddPPCTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
+ const Driver &D = getToolChain().getDriver();
+ const llvm::Triple &T = getToolChain().getTriple();
+ if (Args.getLastArg(options::OPT_mtune_EQ)) {
+ CmdArgs.push_back("-tune-cpu");
+ std::string CPU = ppc::getPPCTuneCPU(Args, T);
+ CmdArgs.push_back(Args.MakeArgString(CPU));
+ }
+
// Select the ABI to use.
const char *ABIName = nullptr;
- const llvm::Triple &T = getToolChain().getTriple();
if (T.isOSBinFormatELF()) {
switch (getToolChain().getArch()) {
case llvm::Triple::ppc64: {
- if ((T.isOSFreeBSD() && T.getOSMajorVersion() >= 13) ||
- T.isOSOpenBSD() || T.isMusl())
+ if (T.isPPC64ELFv2ABI())
ABIName = "elfv2";
else
ABIName = "elfv1";
@@ -2004,14 +1975,29 @@ void Clang::AddPPCTargetArgs(const ArgList &Args,
}
}
- bool IEEELongDouble = false;
+ bool IEEELongDouble = getToolChain().defaultToIEEELongDouble();
+ bool VecExtabi = false;
for (const Arg *A : Args.filtered(options::OPT_mabi_EQ)) {
StringRef V = A->getValue();
- if (V == "ieeelongdouble")
+ if (V == "ieeelongdouble") {
IEEELongDouble = true;
- else if (V == "ibmlongdouble")
+ A->claim();
+ } else if (V == "ibmlongdouble") {
IEEELongDouble = false;
- else if (V != "altivec")
+ A->claim();
+ } else if (V == "vec-default") {
+ VecExtabi = false;
+ A->claim();
+ } else if (V == "vec-extabi") {
+ VecExtabi = true;
+ A->claim();
+ } else if (V == "elfv1") {
+ ABIName = "elfv1";
+ A->claim();
+ } else if (V == "elfv2") {
+ ABIName = "elfv2";
+ A->claim();
+ } else if (V != "altivec")
// The ppc64 linux abis are all "altivec" abis by default. Accept and ignore
// the option if given as we don't have backend support for any targets
// that don't use the altivec abi.
@@ -2019,10 +2005,14 @@ void Clang::AddPPCTargetArgs(const ArgList &Args,
}
if (IEEELongDouble)
CmdArgs.push_back("-mabi=ieeelongdouble");
+ if (VecExtabi) {
+ if (!T.isOSAIX())
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << "-mabi=vec-extabi" << T.str();
+ CmdArgs.push_back("-mabi=vec-extabi");
+ }
- ppc::FloatABI FloatABI =
- ppc::getPPCFloatABI(getToolChain().getDriver(), Args);
-
+ ppc::FloatABI FloatABI = ppc::getPPCFloatABI(D, Args);
if (FloatABI == ppc::FloatABI::Soft) {
// Floating point operations and argument passing are soft.
CmdArgs.push_back("-msoft-float");
@@ -2063,6 +2053,12 @@ static void SetRISCVSmallDataLimit(const ToolChain &TC, const ArgList &Args,
if (Args.hasArg(options::OPT_G)) {
D.Diag(diag::warn_drv_unsupported_sdata);
}
+ } else if (Triple.isAndroid()) {
+ // GP relaxation is not supported on Android.
+ SmallDataLimit = "0";
+ if (Args.hasArg(options::OPT_G)) {
+ D.Diag(diag::warn_drv_unsupported_sdata);
+ }
} else if (Arg *A = Args.getLastArg(options::OPT_G)) {
SmallDataLimit = A->getValue();
}
@@ -2081,18 +2077,57 @@ void Clang::AddRISCVTargetArgs(const ArgList &Args,
SetRISCVSmallDataLimit(getToolChain(), Args, CmdArgs);
- std::string TuneCPU;
-
- if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)) {
- StringRef Name = A->getValue();
+ if (!Args.hasFlag(options::OPT_mimplicit_float,
+ options::OPT_mno_implicit_float, true))
+ CmdArgs.push_back("-no-implicit-float");
- Name = llvm::RISCV::resolveTuneCPUAlias(Name, Triple.isArch64Bit());
- TuneCPU = std::string(Name);
+ if (const Arg *A = Args.getLastArg(options::OPT_mtune_EQ)) {
+ CmdArgs.push_back("-tune-cpu");
+ if (strcmp(A->getValue(), "native") == 0)
+ CmdArgs.push_back(Args.MakeArgString(llvm::sys::getHostCPUName()));
+ else
+ CmdArgs.push_back(A->getValue());
}
- if (!TuneCPU.empty()) {
- CmdArgs.push_back("-tune-cpu");
- CmdArgs.push_back(Args.MakeArgString(TuneCPU));
+ // Handle -mrvv-vector-bits=<bits>
+ if (Arg *A = Args.getLastArg(options::OPT_mrvv_vector_bits_EQ)) {
+ StringRef Val = A->getValue();
+ const Driver &D = getToolChain().getDriver();
+
+ // Get minimum VLen from march.
+ unsigned MinVLen = 0;
+ StringRef Arch = riscv::getRISCVArch(Args, Triple);
+ auto ISAInfo = llvm::RISCVISAInfo::parseArchString(
+ Arch, /*EnableExperimentalExtensions*/ true);
+ // Ignore parsing error.
+ if (!errorToBool(ISAInfo.takeError()))
+ MinVLen = (*ISAInfo)->getMinVLen();
+
+ // If the value is "zvl", use MinVLen from march. Otherwise, try to parse
+ // as integer as long as we have a MinVLen.
+ unsigned Bits = 0;
+ if (Val.equals("zvl") && MinVLen >= llvm::RISCV::RVVBitsPerBlock) {
+ Bits = MinVLen;
+ } else if (!Val.getAsInteger(10, Bits)) {
+ // Only accept power of 2 values beteen RVVBitsPerBlock and 65536 that
+ // at least MinVLen.
+ if (Bits < MinVLen || Bits < llvm::RISCV::RVVBitsPerBlock ||
+ Bits > 65536 || !llvm::isPowerOf2_32(Bits))
+ Bits = 0;
+ }
+
+ // If we got a valid value try to use it.
+ if (Bits != 0) {
+ unsigned VScaleMin = Bits / llvm::RISCV::RVVBitsPerBlock;
+ CmdArgs.push_back(
+ Args.MakeArgString("-mvscale-max=" + llvm::Twine(VScaleMin)));
+ CmdArgs.push_back(
+ Args.MakeArgString("-mvscale-min=" + llvm::Twine(VScaleMin)));
+ } else if (!Val.equals("scalable")) {
+ // Handle the unsupported values passed to mrvv-vector-bits.
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getSpelling() << Val;
+ }
}
}
@@ -2112,12 +2147,32 @@ void Clang::AddSparcTargetArgs(const ArgList &Args,
CmdArgs.push_back("-mfloat-abi");
CmdArgs.push_back("hard");
}
+
+ 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);
+
+ CmdArgs.push_back("-tune-cpu");
+ CmdArgs.push_back(Args.MakeArgString(TuneCPU));
+ }
}
void Clang::AddSystemZTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
- bool HasBackchain = Args.hasFlag(options::OPT_mbackchain,
- options::OPT_mno_backchain, false);
+ if (const Arg *A = Args.getLastArg(options::OPT_mtune_EQ)) {
+ CmdArgs.push_back("-tune-cpu");
+ if (strcmp(A->getValue(), "native") == 0)
+ CmdArgs.push_back(Args.MakeArgString(llvm::sys::getHostCPUName()));
+ else
+ CmdArgs.push_back(A->getValue());
+ }
+
+ bool HasBackchain =
+ Args.hasFlag(options::OPT_mbackchain, options::OPT_mno_backchain, false);
bool HasPackedStack = Args.hasFlag(options::OPT_mpacked_stack,
options::OPT_mno_packed_stack, false);
systemz::FloatABI FloatABI =
@@ -2173,15 +2228,21 @@ 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;
+ << A->getSpelling() << Value;
}
} else if (D.IsCLMode()) {
CmdArgs.push_back("-mllvm");
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");
@@ -2191,10 +2252,10 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
// Handle -mtune.
- // Default to "generic" unless -march is present or targetting the PS4.
+ // Default to "generic" unless -march is present or targetting the PS4/PS5.
std::string TuneCPU;
if (!Args.hasArg(clang::driver::options::OPT_march_EQ) &&
- !getToolChain().getTriple().isPS4CPU())
+ !getToolChain().getTriple().isPS())
TuneCPU = "generic";
// Override based on -mtune.
@@ -2222,8 +2283,8 @@ void Clang::AddHexagonTargetArgs(const ArgList &Args,
if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
CmdArgs.push_back("-mllvm");
- CmdArgs.push_back(Args.MakeArgString("-hexagon-small-data-threshold=" +
- Twine(G.getValue())));
+ CmdArgs.push_back(
+ Args.MakeArgString("-hexagon-small-data-threshold=" + Twine(*G)));
}
if (!Args.hasArg(options::OPT_fno_short_enums))
@@ -2253,7 +2314,7 @@ void Clang::AddLanaiTargetArgs(const ArgList &Args,
if (Mregparm != 4) {
getToolChain().getDriver().Diag(
diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << Value;
+ << A->getSpelling() << Value;
}
}
}
@@ -2263,10 +2324,8 @@ void Clang::AddWebAssemblyTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
// Default to "hidden" visibility.
if (!Args.hasArg(options::OPT_fvisibility_EQ,
- options::OPT_fvisibility_ms_compat)) {
- CmdArgs.push_back("-fvisibility");
- CmdArgs.push_back("hidden");
- }
+ options::OPT_fvisibility_ms_compat))
+ CmdArgs.push_back("-fvisibility=hidden");
}
void Clang::AddVETargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
@@ -2288,7 +2347,8 @@ void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename,
if (!CompilationDatabase) {
std::error_code EC;
auto File = std::make_unique<llvm::raw_fd_ostream>(
- Filename, EC, llvm::sys::fs::OF_TextWithCRLF);
+ Filename, EC,
+ llvm::sys::fs::OF_TextWithCRLF | llvm::sys::fs::OF_Append);
if (EC) {
D.Diag(clang::diag::err_drv_compilationdatabase) << Filename
<< EC.message();
@@ -2302,7 +2362,8 @@ void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename,
CWD = ".";
CDB << "{ \"directory\": \"" << escape(*CWD) << "\"";
CDB << ", \"file\": \"" << escape(Input.getFilename()) << "\"";
- CDB << ", \"output\": \"" << escape(Output.getFilename()) << "\"";
+ if (Output.isFilename())
+ CDB << ", \"output\": \"" << escape(Output.getFilename()) << "\"";
CDB << ", \"arguments\": [\"" << escape(D.ClangExecutable) << "\"";
SmallString<128> Buf;
Buf = "-x";
@@ -2314,6 +2375,8 @@ void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename,
CDB << ", \"" << escape(Buf) << "\"";
}
CDB << ", \"" << escape(Input.getFilename()) << "\"";
+ if (Output.isFilename())
+ CDB << ", \"-o\", \"" << escape(Output.getFilename()) << "\"";
for (auto &A: Args) {
auto &O = A->getOption();
// Skip language selection, which is positional.
@@ -2327,6 +2390,9 @@ void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename,
// Skip inputs.
if (O.getKind() == Option::InputClass)
continue;
+ // Skip output.
+ if (O.getID() == options::OPT_o)
+ continue;
// All other arguments are quoted and appended.
ArgStringList ASL;
A->render(Args, ASL);
@@ -2400,6 +2466,11 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
DefaultIncrementalLinkerCompatible))
CmdArgs.push_back("-mincremental-linker-compatible");
+ Args.AddLastArg(CmdArgs, options::OPT_femit_dwarf_unwind_EQ);
+
+ Args.addOptInFlag(CmdArgs, options::OPT_femit_compact_unwind_non_canonical,
+ options::OPT_fno_emit_compact_unwind_non_canonical);
+
// If you add more args here, also add them to the block below that
// starts with "// If CollectArgsForIntegratedAssembler() isn't called below".
@@ -2411,7 +2482,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 :
@@ -2429,7 +2500,7 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
ImplicitIt = A->getValue();
if (!CheckARMImplicitITArg(ImplicitIt))
D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << ImplicitIt;
+ << A->getSpelling() << ImplicitIt;
continue;
default:
break;
@@ -2450,11 +2521,18 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
switch (C.getDefaultToolChain().getArch()) {
default:
break;
+ case llvm::Triple::wasm32:
+ case llvm::Triple::wasm64:
+ if (Value == "--no-type-check") {
+ CmdArgs.push_back("-mno-type-check");
+ continue;
+ }
+ break;
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
case llvm::Triple::arm:
case llvm::Triple::armeb:
- if (Value.startswith("-mimplicit-it=")) {
+ if (Value.starts_with("-mimplicit-it=")) {
// Only store the value; the last value set takes effect.
ImplicitIt = Value.split("=").second;
if (CheckARMImplicitITArg(ImplicitIt))
@@ -2479,12 +2557,12 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
CmdArgs.push_back("-use-tcc-in-div");
continue;
}
- if (Value.startswith("-msoft-float")) {
+ if (Value.starts_with("-msoft-float")) {
CmdArgs.push_back("-target-feature");
CmdArgs.push_back("+soft-float");
continue;
}
- if (Value.startswith("-mhard-float")) {
+ if (Value.starts_with("-mhard-float")) {
CmdArgs.push_back("-target-feature");
CmdArgs.push_back("-soft-float");
continue;
@@ -2521,8 +2599,8 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
CmdArgs.push_back("-massembler-no-warn");
} else if (Value == "--noexecstack") {
UseNoExecStack = true;
- } else if (Value.startswith("-compress-debug-sections") ||
- Value.startswith("--compress-debug-sections") ||
+ } else if (Value.starts_with("-compress-debug-sections") ||
+ Value.starts_with("--compress-debug-sections") ||
Value == "-nocompress-debug-sections" ||
Value == "--nocompress-debug-sections") {
CmdArgs.push_back(Value.data());
@@ -2532,46 +2610,46 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
} else if (Value == "-mrelax-relocations=no" ||
Value == "--mrelax-relocations=no") {
UseRelaxRelocations = false;
- } else if (Value.startswith("-I")) {
+ } else if (Value.starts_with("-I")) {
CmdArgs.push_back(Value.data());
// We need to consume the next argument if the current arg is a plain
// -I. The next arg will be the include directory.
if (Value == "-I")
TakeNextArg = true;
- } else if (Value.startswith("-gdwarf-")) {
+ } else if (Value.starts_with("-gdwarf-")) {
// "-gdwarf-N" options are not cc1as options.
unsigned DwarfVersion = DwarfVersionNum(Value);
if (DwarfVersion == 0) { // Send it onward, and let cc1as complain.
CmdArgs.push_back(Value.data());
} else {
RenderDebugEnablingArgs(Args, CmdArgs,
- codegenoptions::DebugInfoConstructor,
+ llvm::codegenoptions::DebugInfoConstructor,
DwarfVersion, llvm::DebuggerKind::Default);
}
- } else if (Value.startswith("-mcpu") || Value.startswith("-mfpu") ||
- Value.startswith("-mhwdiv") || Value.startswith("-march")) {
+ } else if (Value.starts_with("-mcpu") || Value.starts_with("-mfpu") ||
+ Value.starts_with("-mhwdiv") || Value.starts_with("-march")) {
// Do nothing, we'll validate it later.
} else if (Value == "-defsym") {
- if (A->getNumValues() != 2) {
- D.Diag(diag::err_drv_defsym_invalid_format) << Value;
- break;
- }
- const char *S = A->getValue(1);
- auto Pair = StringRef(S).split('=');
- auto Sym = Pair.first;
- auto SVal = Pair.second;
-
- if (Sym.empty() || SVal.empty()) {
- D.Diag(diag::err_drv_defsym_invalid_format) << S;
- break;
- }
- int64_t IVal;
- if (SVal.getAsInteger(0, IVal)) {
- D.Diag(diag::err_drv_defsym_invalid_symval) << SVal;
- break;
- }
- CmdArgs.push_back(Value.data());
- TakeNextArg = true;
+ if (A->getNumValues() != 2) {
+ D.Diag(diag::err_drv_defsym_invalid_format) << Value;
+ break;
+ }
+ const char *S = A->getValue(1);
+ auto Pair = StringRef(S).split('=');
+ auto Sym = Pair.first;
+ auto SVal = Pair.second;
+
+ if (Sym.empty() || SVal.empty()) {
+ D.Diag(diag::err_drv_defsym_invalid_format) << S;
+ break;
+ }
+ int64_t IVal;
+ if (SVal.getAsInteger(0, IVal)) {
+ D.Diag(diag::err_drv_defsym_invalid_symval) << SVal;
+ break;
+ }
+ CmdArgs.push_back(Value.data());
+ TakeNextArg = true;
} else if (Value == "-fdebug-compilation-dir") {
CmdArgs.push_back("-fdebug-compilation-dir");
TakeNextArg = true;
@@ -2585,14 +2663,14 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
D.PrintVersion(C, llvm::outs());
} else {
D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << Value;
+ << A->getSpelling() << Value;
}
}
}
if (ImplicitIt.size())
AddARMImplicitITArgs(Args, CmdArgs, ImplicitIt);
- if (UseRelaxRelocations)
- CmdArgs.push_back("--mrelax-relocations");
+ if (!UseRelaxRelocations)
+ CmdArgs.push_back("-mrelax-relocations=no");
if (UseNoExecStack)
CmdArgs.push_back("-mnoexecstack");
if (MipsTargetFeature != nullptr) {
@@ -2604,6 +2682,53 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
if (C.getDriver().embedBitcodeEnabled() ||
C.getDriver().embedBitcodeMarkerOnly())
Args.AddLastArg(CmdArgs, options::OPT_fembed_bitcode_EQ);
+
+ if (const char *AsSecureLogFile = getenv("AS_SECURE_LOG_FILE")) {
+ CmdArgs.push_back("-as-secure-log-file");
+ CmdArgs.push_back(Args.MakeArgString(AsSecureLogFile));
+ }
+}
+
+static StringRef EnumComplexRangeToStr(LangOptions::ComplexRangeKind Range) {
+ StringRef RangeStr = "";
+ switch (Range) {
+ case LangOptions::ComplexRangeKind::CX_Limited:
+ return "-fcx-limited-range";
+ break;
+ case LangOptions::ComplexRangeKind::CX_Fortran:
+ return "-fcx-fortran-rules";
+ break;
+ default:
+ return RangeStr;
+ break;
+ }
+}
+
+static void EmitComplexRangeDiag(const Driver &D,
+ LangOptions::ComplexRangeKind Range1,
+ LangOptions::ComplexRangeKind Range2) {
+ if (Range1 != LangOptions::ComplexRangeKind::CX_Full)
+ D.Diag(clang::diag::warn_drv_overriding_option)
+ << EnumComplexRangeToStr(Range1) << EnumComplexRangeToStr(Range2);
+}
+
+static std::string
+RenderComplexRangeOption(LangOptions::ComplexRangeKind Range) {
+ std::string ComplexRangeStr = "-complex-range=";
+ switch (Range) {
+ case LangOptions::ComplexRangeKind::CX_Full:
+ ComplexRangeStr += "full";
+ break;
+ case LangOptions::ComplexRangeKind::CX_Limited:
+ ComplexRangeStr += "limited";
+ break;
+ case LangOptions::ComplexRangeKind::CX_Fortran:
+ ComplexRangeStr += "fortran";
+ break;
+ default:
+ assert(0 && "Unexpected range option");
+ }
+ return ComplexRangeStr;
}
static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
@@ -2617,6 +2742,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;
@@ -2631,6 +2757,8 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
StringRef FPModel = "";
// -ffp-exception-behavior options: strict, maytrap, ignore
StringRef FPExceptionBehavior = "";
+ // -ffp-eval-method options: double, extended, source
+ StringRef FPEvalMethod = "";
const llvm::DenormalMode DefaultDenormalFPMath =
TC.getDefaultDenormalModeForType(Args, JA);
const llvm::DenormalMode DefaultDenormalFP32Math =
@@ -2638,9 +2766,19 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
llvm::DenormalMode DenormalFPMath = DefaultDenormalFPMath;
llvm::DenormalMode DenormalFP32Math = DefaultDenormalFP32Math;
- StringRef FPContract = "";
+ // 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;
+ StringRef LastSeenFfpContractOption;
+ bool SeenUnsafeMathModeOption = false;
+ if (!JA.isDeviceOffloading(Action::OFK_Cuda) &&
+ !JA.isOffloading(Action::OFK_HIP))
+ FPContract = "on";
bool StrictFPModel = false;
-
+ StringRef Float16ExcessPrecision = "";
+ StringRef BFloat16ExcessPrecision = "";
+ LangOptions::ComplexRangeKind Range = LangOptions::ComplexRangeKind::CX_None;
+ std::string ComplexRangeStr = "";
if (const Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
CmdArgs.push_back("-mlimit-float-precision");
@@ -2653,17 +2791,36 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
switch (optID) {
default:
break;
+ case options::OPT_fcx_limited_range: {
+ EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Limited);
+ Range = LangOptions::ComplexRangeKind::CX_Limited;
+ break;
+ }
+ case options::OPT_fno_cx_limited_range:
+ EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Full);
+ Range = LangOptions::ComplexRangeKind::CX_Full;
+ break;
+ case options::OPT_fcx_fortran_rules: {
+ EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Fortran);
+ Range = LangOptions::ComplexRangeKind::CX_Fortran;
+ break;
+ }
+ case options::OPT_fno_cx_fortran_rules:
+ EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Full);
+ Range = LangOptions::ComplexRangeKind::CX_Full;
+ break;
case options::OPT_ffp_model_EQ: {
// If -ffp-model= is seen, reset to fno-fast-math
HonorINFs = true;
HonorNaNs = true;
+ ApproxFunc = false;
// Turning *off* -ffast-math restores the toolchain default.
MathErrno = TC.IsMathErrnoDefault();
AssociativeMath = false;
ReciprocalMath = false;
SignedZeros = true;
// -fno_fast_math restores default denormal and fpcontract handling
- FPContract = "";
+ FPContract = "on";
DenormalFPMath = llvm::DenormalMode::getIEEE();
// FIXME: The target may have picked a non-IEEE default mode here based on
@@ -2673,9 +2830,8 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
StringRef Val = A->getValue();
if (OFastEnabled && !Val.equals("fast")) {
// Only -ffp-model=fast is compatible with OFast, ignore.
- D.Diag(clang::diag::warn_drv_overriding_flag_option)
- << Args.MakeArgString("-ffp-model=" + Val)
- << "-Ofast";
+ D.Diag(clang::diag::warn_drv_overriding_option)
+ << Args.MakeArgString("-ffp-model=" + Val) << "-Ofast";
break;
}
StrictFPModel = false;
@@ -2683,12 +2839,10 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
// ffp-model= is a Driver option, it is entirely rewritten into more
// granular options before being passed into cc1.
// 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);
- FPContract = "";
- }
+ if (!FPModel.empty() && !FPModel.equals(Val))
+ D.Diag(clang::diag::warn_drv_overriding_option)
+ << Args.MakeArgString("-ffp-model=" + FPModel)
+ << Args.MakeArgString("-ffp-model=" + Val);
if (Val.equals("fast")) {
optID = options::OPT_ffast_math;
FPModel = Val;
@@ -2696,7 +2850,7 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
} else if (Val.equals("precise")) {
optID = options::OPT_ffp_contract;
FPModel = Val;
- FPContract = "fast";
+ FPContract = "on";
PreciseFPModel = true;
} else if (Val.equals("strict")) {
StrictFPModel = true;
@@ -2707,9 +2861,9 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
TrappingMath = true;
} else
D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << Val;
+ << A->getSpelling() << Val;
break;
- }
+ }
}
switch (optID) {
@@ -2721,6 +2875,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;
@@ -2733,9 +2889,10 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
if (!TrappingMathPresent && !FPExceptionBehavior.empty() &&
!FPExceptionBehavior.equals("strict"))
// Warn that previous value of option is overridden.
- D.Diag(clang::diag::warn_drv_overriding_flag_option)
- << Args.MakeArgString("-ffp-exception-behavior=" + FPExceptionBehavior)
- << "-ftrapping-math";
+ D.Diag(clang::diag::warn_drv_overriding_option)
+ << Args.MakeArgString("-ffp-exception-behavior=" +
+ FPExceptionBehavior)
+ << "-ftrapping-math";
TrappingMath = true;
TrappingMathPresent = true;
FPExceptionBehavior = "strict";
@@ -2744,9 +2901,10 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
if (!TrappingMathPresent && !FPExceptionBehavior.empty() &&
!FPExceptionBehavior.equals("ignore"))
// Warn that previous value of option is overridden.
- D.Diag(clang::diag::warn_drv_overriding_flag_option)
- << Args.MakeArgString("-ffp-exception-behavior=" + FPExceptionBehavior)
- << "-fno-trapping-math";
+ D.Diag(clang::diag::warn_drv_overriding_option)
+ << Args.MakeArgString("-ffp-exception-behavior=" +
+ FPExceptionBehavior)
+ << "-fno-trapping-math";
TrappingMath = false;
TrappingMathPresent = true;
FPExceptionBehavior = "ignore";
@@ -2764,6 +2922,7 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
case options::OPT_fdenormal_fp_math_EQ:
DenormalFPMath = llvm::parseDenormalFPAttribute(A->getValue());
+ DenormalFP32Math = DenormalFPMath;
if (!DenormalFPMath.isValid()) {
D.Diag(diag::err_drv_invalid_value)
<< A->getAsString(Args) << A->getValue();
@@ -2782,15 +2941,17 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
case options::OPT_ffp_contract: {
StringRef Val = A->getValue();
if (PreciseFPModel) {
- // -ffp-model=precise enables ffp-contract=fast as a side effect
- // the FPContract value has already been set to a string literal
- // and the Val string isn't a pertinent value.
+ // -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"))
+ } else if (Val.equals("fast") || Val.equals("on") || Val.equals("off") ||
+ Val.equals("fast-honor-pragmas")) {
FPContract = Val;
- else
+ LastSeenFfpContractOption = Val;
+ } else
D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << Val;
+ << A->getSpelling() << Val;
break;
}
@@ -2807,9 +2968,10 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
if (!TrappingMathPresent && !FPExceptionBehavior.empty() &&
!FPExceptionBehavior.equals(Val))
// Warn that previous value of option is overridden.
- D.Diag(clang::diag::warn_drv_overriding_flag_option)
- << Args.MakeArgString("-ffp-exception-behavior=" + FPExceptionBehavior)
- << Args.MakeArgString("-ffp-exception-behavior=" + Val);
+ D.Diag(clang::diag::warn_drv_overriding_option)
+ << Args.MakeArgString("-ffp-exception-behavior=" +
+ FPExceptionBehavior)
+ << Args.MakeArgString("-ffp-exception-behavior=" + Val);
TrappingMath = TrappingMathPresent = false;
if (Val.equals("ignore") || Val.equals("maytrap"))
FPExceptionBehavior = Val;
@@ -2818,10 +2980,44 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
TrappingMath = TrappingMathPresent = true;
} else
D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << Val;
+ << A->getSpelling() << Val;
+ break;
+ }
+
+ // Validate and pass through -ffp-eval-method option.
+ case options::OPT_ffp_eval_method_EQ: {
+ StringRef Val = A->getValue();
+ if (Val.equals("double") || Val.equals("extended") ||
+ Val.equals("source"))
+ FPEvalMethod = Val;
+ else
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getSpelling() << Val;
break;
}
+ case options::OPT_fexcess_precision_EQ: {
+ StringRef Val = A->getValue();
+ const llvm::Triple::ArchType Arch = TC.getArch();
+ if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) {
+ if (Val.equals("standard") || Val.equals("fast"))
+ Float16ExcessPrecision = Val;
+ // To make it GCC compatible, allow the value of "16" which
+ // means disable excess precision, the same meaning than clang's
+ // equivalent value "none".
+ else if (Val.equals("16"))
+ Float16ExcessPrecision = "none";
+ else
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getSpelling() << Val;
+ } else {
+ if (!(Val.equals("standard") || Val.equals("fast")))
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getSpelling() << Val;
+ }
+ BFloat16ExcessPrecision = Float16ExcessPrecision;
+ break;
+ }
case options::OPT_ffinite_math_only:
HonorINFs = false;
HonorNaNs = false;
@@ -2835,38 +3031,56 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
AssociativeMath = true;
ReciprocalMath = true;
SignedZeros = false;
+ ApproxFunc = true;
TrappingMath = false;
FPExceptionBehavior = "";
+ FPContract = "fast";
+ SeenUnsafeMathModeOption = true;
break;
case options::OPT_fno_unsafe_math_optimizations:
AssociativeMath = false;
ReciprocalMath = false;
SignedZeros = true;
+ ApproxFunc = false;
TrappingMath = true;
FPExceptionBehavior = "strict";
// The target may have opted to flush by default, so force IEEE.
DenormalFPMath = llvm::DenormalMode::getIEEE();
DenormalFP32Math = llvm::DenormalMode::getIEEE();
+ if (!JA.isDeviceOffloading(Action::OFK_Cuda) &&
+ !JA.isOffloading(Action::OFK_HIP)) {
+ if (LastSeenFfpContractOption != "") {
+ FPContract = LastSeenFfpContractOption;
+ } else if (SeenUnsafeMathModeOption)
+ FPContract = "on";
+ }
break;
case options::OPT_Ofast:
// If -Ofast is the optimization level, then -ffast-math should be enabled
if (!OFastEnabled)
continue;
- LLVM_FALLTHROUGH;
- case options::OPT_ffast_math:
+ [[fallthrough]];
+ case options::OPT_ffast_math: {
HonorINFs = false;
HonorNaNs = false;
MathErrno = false;
AssociativeMath = true;
ReciprocalMath = true;
+ ApproxFunc = true;
SignedZeros = false;
TrappingMath = false;
RoundingFPMath = false;
+ FPExceptionBehavior = "";
// If fast-math is set then set the fp-contract mode to fast.
FPContract = "fast";
+ SeenUnsafeMathModeOption = true;
+ // ffast-math enables fortran rules for complex multiplication and
+ // division.
+ Range = LangOptions::ComplexRangeKind::CX_Limited;
break;
+ }
case options::OPT_fno_fast_math:
HonorINFs = true;
HonorNaNs = true;
@@ -2876,33 +3090,39 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
MathErrno = TC.IsMathErrnoDefault();
AssociativeMath = false;
ReciprocalMath = false;
+ ApproxFunc = false;
SignedZeros = true;
- TrappingMath = false;
- RoundingFPMath = false;
// -fno_fast_math restores default denormal and fpcontract handling
DenormalFPMath = DefaultDenormalFPMath;
DenormalFP32Math = llvm::DenormalMode::getIEEE();
- FPContract = "";
+ if (!JA.isDeviceOffloading(Action::OFK_Cuda) &&
+ !JA.isOffloading(Action::OFK_HIP)) {
+ if (LastSeenFfpContractOption != "") {
+ FPContract = LastSeenFfpContractOption;
+ } else if (SeenUnsafeMathModeOption)
+ FPContract = "on";
+ }
break;
}
if (StrictFPModel) {
// If -ffp-model=strict has been specified on command line but
// subsequent options conflict then emit warning diagnostic.
- if (HonorINFs && HonorNaNs &&
- !AssociativeMath && !ReciprocalMath &&
- SignedZeros && TrappingMath && RoundingFPMath &&
- (FPContract.equals("off") || FPContract.empty()) &&
- DenormalFPMath == llvm::DenormalMode::getIEEE() &&
- DenormalFP32Math == llvm::DenormalMode::getIEEE())
+ if (HonorINFs && HonorNaNs && !AssociativeMath && !ReciprocalMath &&
+ SignedZeros && TrappingMath && RoundingFPMath && !ApproxFunc &&
+ DenormalFPMath == llvm::DenormalMode::getIEEE() &&
+ DenormalFP32Math == llvm::DenormalMode::getIEEE() &&
+ FPContract.equals("off"))
// OK: Current Arg doesn't conflict with -ffp-model=strict
;
else {
StrictFPModel = false;
FPModel = "";
- D.Diag(clang::diag::warn_drv_overriding_flag_option)
- << "-ffp-model=strict" <<
- ((A->getNumValues() == 0) ? A->getSpelling()
- : Args.MakeArgString(A->getSpelling() + A->getValue()));
+ auto RHS = (A->getNumValues() == 0)
+ ? A->getSpelling()
+ : Args.MakeArgString(A->getSpelling() + A->getValue());
+ if (RHS != "-ffp-model=strict")
+ D.Diag(clang::diag::warn_drv_overriding_option)
+ << "-ffp-model=strict" << RHS;
}
}
@@ -2916,12 +3136,15 @@ 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");
- if (!MathErrno && AssociativeMath && ReciprocalMath && !SignedZeros &&
- !TrappingMath)
- CmdArgs.push_back("-menable-unsafe-fp-math");
+ if (AssociativeMath && ReciprocalMath && !SignedZeros && ApproxFunc &&
+ !TrappingMath)
+ CmdArgs.push_back("-funsafe-math-optimizations");
if (!SignedZeros)
CmdArgs.push_back("-fno-signed-zeros");
@@ -2966,12 +3189,22 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
CmdArgs.push_back(Args.MakeArgString("-ffp-exception-behavior=" +
FPExceptionBehavior));
+ if (!FPEvalMethod.empty())
+ CmdArgs.push_back(Args.MakeArgString("-ffp-eval-method=" + FPEvalMethod));
+
+ if (!Float16ExcessPrecision.empty())
+ CmdArgs.push_back(Args.MakeArgString("-ffloat16-excess-precision=" +
+ Float16ExcessPrecision));
+ if (!BFloat16ExcessPrecision.empty())
+ CmdArgs.push_back(Args.MakeArgString("-fbfloat16-excess-precision=" +
+ BFloat16ExcessPrecision));
+
ParseMRecip(D, Args, CmdArgs);
// -ffast-math enables the __FAST_MATH__ preprocessor macro, but check for the
// individual features enabled by -ffast-math instead of the option itself as
// that's consistent with gcc's behaviour.
- if (!HonorINFs && !HonorNaNs && !MathErrno && AssociativeMath &&
+ if (!HonorINFs && !HonorNaNs && !MathErrno && AssociativeMath && ApproxFunc &&
ReciprocalMath && !SignedZeros && !TrappingMath && !RoundingFPMath) {
CmdArgs.push_back("-ffast-math");
if (FPModel.equals("fast")) {
@@ -2982,9 +3215,9 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
// Enable -ffp-contract=fast
CmdArgs.push_back(Args.MakeArgString("-ffp-contract=fast"));
else
- D.Diag(clang::diag::warn_drv_overriding_flag_option)
- << "-ffp-model=fast"
- << Args.MakeArgString("-ffp-contract=" + FPContract);
+ D.Diag(clang::diag::warn_drv_overriding_option)
+ << "-ffp-model=fast"
+ << Args.MakeArgString("-ffp-contract=" + FPContract);
}
}
@@ -3001,17 +3234,24 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
if (Args.hasFlag(options::OPT_fno_strict_float_cast_overflow,
options::OPT_fstrict_float_cast_overflow, false))
CmdArgs.push_back("-fno-strict-float-cast-overflow");
+
+ if (Range != LangOptions::ComplexRangeKind::CX_None)
+ ComplexRangeStr = RenderComplexRangeOption(Range);
+ if (!ComplexRangeStr.empty())
+ CmdArgs.push_back(Args.MakeArgString(ComplexRangeStr));
+ if (Args.hasArg(options::OPT_fcx_limited_range))
+ CmdArgs.push_back("-fcx-limited-range");
+ if (Args.hasArg(options::OPT_fcx_fortran_rules))
+ CmdArgs.push_back("-fcx-fortran-rules");
+ if (Args.hasArg(options::OPT_fno_cx_limited_range))
+ CmdArgs.push_back("-fno-cx-limited-range");
+ if (Args.hasArg(options::OPT_fno_cx_fortran_rules))
+ CmdArgs.push_back("-fno-cx-fortran-rules");
}
static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs,
const llvm::Triple &Triple,
const InputInfo &Input) {
- // Enable region store model by default.
- CmdArgs.push_back("-analyzer-store=region");
-
- // Treat blocks as analysis entry points.
- CmdArgs.push_back("-analyzer-opt-analyze-nested-blocks");
-
// Add default argument set.
if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) {
CmdArgs.push_back("-analyzer-checker=core");
@@ -3029,8 +3269,8 @@ static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs,
CmdArgs.push_back("-analyzer-checker=unix.cstring.NullArg");
}
- // Disable some unix checkers for PS4.
- if (Triple.isPS4CPU()) {
+ // Disable some unix checkers for PS4/PS5.
+ if (Triple.isPS()) {
CmdArgs.push_back("-analyzer-disable-checker=unix.API");
CmdArgs.push_back("-analyzer-disable-checker=unix.Vfork");
}
@@ -3048,7 +3288,7 @@ static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs,
if (types::isCXX(Input.getType()))
CmdArgs.push_back("-analyzer-checker=cplusplus");
- if (!Triple.isPS4CPU()) {
+ if (!Triple.isPS()) {
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.UncheckedReturn");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.gets");
@@ -3078,6 +3318,16 @@ static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs,
Args.AddAllArgValues(CmdArgs, options::OPT_Xanalyzer);
}
+static bool isValidSymbolName(StringRef S) {
+ if (S.empty())
+ return false;
+
+ if (std::isdigit(S[0]))
+ return false;
+
+ return llvm::all_of(S, [](char C) { return std::isalnum(C) || C == '_'; });
+}
+
static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
const ArgList &Args, ArgStringList &CmdArgs,
bool KernelOrKext) {
@@ -3104,6 +3354,12 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
StackProtectorLevel = LangOptions::SSPStrong;
else if (A->getOption().matches(options::OPT_fstack_protector_all))
StackProtectorLevel = LangOptions::SSPReq;
+
+ if (EffectiveTriple.isBPF() && StackProtectorLevel != LangOptions::SSPOff) {
+ D.Diag(diag::warn_drv_unsupported_option_for_target)
+ << A->getSpelling() << EffectiveTriple.getTriple();
+ StackProtectorLevel = DefaultStackProtectorLevel;
+ }
} else {
StackProtectorLevel = DefaultStackProtectorLevel;
}
@@ -3116,7 +3372,7 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
// --param ssp-buffer-size=
for (const Arg *A : Args.filtered(options::OPT__param)) {
StringRef Str(A->getValue());
- if (Str.startswith("ssp-buffer-size=")) {
+ if (Str.starts_with("ssp-buffer-size=")) {
if (StackProtectorLevel) {
CmdArgs.push_back("-stack-protector-buffer-size");
// FIXME: Verify the argument is a valid integer.
@@ -3129,14 +3385,42 @@ 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::isHardTPSupported(EffectiveTriple)) {
+ 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-tpidruro");
+ }
if (EffectiveTriple.isAArch64() && Value != "sysreg" && Value != "global") {
D.Diag(diag::err_drv_invalid_value_with_suggestion)
<< A->getOption().getName() << Value << "sysreg global";
@@ -3147,7 +3431,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;
@@ -3155,6 +3440,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);
}
@@ -3174,6 +3465,16 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
}
A->render(Args, CmdArgs);
}
+
+ if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_symbol_EQ)) {
+ StringRef Value = A->getValue();
+ if (!isValidSymbolName(Value)) {
+ D.Diag(diag::err_drv_argument_only_allowed_with)
+ << A->getOption().getName() << "legal symbol name";
+ return;
+ }
+ A->render(Args, CmdArgs);
+ }
}
static void RenderSCPOptions(const ToolChain &TC, const ArgList &Args,
@@ -3184,12 +3485,11 @@ static void RenderSCPOptions(const ToolChain &TC, const ArgList &Args,
return;
if (!EffectiveTriple.isX86() && !EffectiveTriple.isSystemZ() &&
- !EffectiveTriple.isPPC64())
+ !EffectiveTriple.isPPC64() && !EffectiveTriple.isAArch64())
return;
- if (Args.hasFlag(options::OPT_fstack_clash_protection,
- options::OPT_fno_stack_clash_protection, false))
- CmdArgs.push_back("-fstack-clash-protection");
+ Args.addOptInFlag(CmdArgs, options::OPT_fstack_clash_protection,
+ options::OPT_fno_stack_clash_protection);
}
static void RenderTrivialAutoVarInitOptions(const Driver &D,
@@ -3210,7 +3510,7 @@ static void RenderTrivialAutoVarInitOptions(const Driver &D,
TrivialAutoVarInit = Val;
else
D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << Val;
+ << A->getSpelling() << Val;
break;
}
}
@@ -3229,8 +3529,6 @@ static void RenderTrivialAutoVarInitOptions(const Driver &D,
}
if (!TrivialAutoVarInit.empty()) {
- if (TrivialAutoVarInit == "zero" && !Args.hasArg(options::OPT_enable_trivial_var_init_zero))
- D.Diag(diag::err_drv_trivial_auto_var_init_zero_disabled);
CmdArgs.push_back(
Args.MakeArgString("-ftrivial-auto-var-init=" + TrivialAutoVarInit));
}
@@ -3249,6 +3547,20 @@ static void RenderTrivialAutoVarInitOptions(const Driver &D,
CmdArgs.push_back(
Args.MakeArgString("-ftrivial-auto-var-init-stop-after=" + Val));
}
+
+ if (Arg *A = Args.getLastArg(options::OPT_ftrivial_auto_var_init_max_size)) {
+ if (!Args.hasArg(options::OPT_ftrivial_auto_var_init) ||
+ StringRef(
+ Args.getLastArg(options::OPT_ftrivial_auto_var_init)->getValue()) ==
+ "uninitialized")
+ D.Diag(diag::err_drv_trivial_auto_var_init_max_size_missing_dependency);
+ A->claim();
+ StringRef Val = A->getValue();
+ if (std::stoi(Val.str()) <= 0)
+ D.Diag(diag::err_drv_trivial_auto_var_init_max_size_invalid_value);
+ CmdArgs.push_back(
+ Args.MakeArgString("-ftrivial-auto-var-init-max-size=" + Val));
+ }
}
static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs,
@@ -3272,6 +3584,9 @@ static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs,
if (Arg *A = Args.getLastArg(options::OPT_cl_std_EQ)) {
std::string CLStdStr = std::string("-cl-std=") + A->getValue();
CmdArgs.push_back(Args.MakeArgString(CLStdStr));
+ } else if (Arg *A = Args.getLastArg(options::OPT_cl_ext_EQ)) {
+ std::string CLExtStr = std::string("-cl-ext=") + A->getValue();
+ CmdArgs.push_back(Args.MakeArgString(CLExtStr));
}
for (const auto &Arg : ForwardedArguments)
@@ -3287,6 +3602,46 @@ static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs,
}
}
+static void RenderHLSLOptions(const ArgList &Args, ArgStringList &CmdArgs,
+ types::ID InputType) {
+ const unsigned ForwardedArguments[] = {options::OPT_dxil_validator_version,
+ options::OPT_D,
+ options::OPT_I,
+ options::OPT_S,
+ options::OPT_O,
+ options::OPT_emit_llvm,
+ options::OPT_emit_obj,
+ options::OPT_disable_llvm_passes,
+ options::OPT_fnative_half_type,
+ options::OPT_hlsl_entrypoint};
+ if (!types::isHLSL(InputType))
+ return;
+ for (const auto &Arg : ForwardedArguments)
+ if (const auto *A = Args.getLastArg(Arg))
+ A->renderAsInput(Args, CmdArgs);
+ // Add the default headers if dxc_no_stdinc is not set.
+ if (!Args.hasArg(options::OPT_dxc_no_stdinc) &&
+ !Args.hasArg(options::OPT_nostdinc))
+ CmdArgs.push_back("-finclude-default-header");
+}
+
+static void RenderOpenACCOptions(const Driver &D, const ArgList &Args,
+ ArgStringList &CmdArgs, types::ID InputType) {
+ if (!Args.hasArg(options::OPT_fopenacc))
+ return;
+
+ CmdArgs.push_back("-fopenacc");
+
+ if (Arg *A = Args.getLastArg(options::OPT_openacc_macro_override)) {
+ StringRef Value = A->getValue();
+ int Version;
+ if (!Value.getAsInteger(10, Version))
+ A->renderAsInput(Args, CmdArgs);
+ else
+ D.Diag(diag::err_drv_clang_unsupported) << Value;
+ }
+}
+
static void RenderARCMigrateToolOptions(const Driver &D, const ArgList &Args,
ArgStringList &CmdArgs) {
bool ARCMTEnabled = false;
@@ -3355,7 +3710,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);
}
}
@@ -3373,20 +3728,13 @@ static void RenderBuiltinOptions(const ToolChain &TC, const llvm::Triple &T,
UseBuiltins = false;
// Process the -fno-builtin-* options.
- for (const auto &Arg : Args) {
- const Option &O = Arg->getOption();
- if (!O.matches(options::OPT_fno_builtin_))
- continue;
-
- Arg->claim();
+ for (const Arg *A : Args.filtered(options::OPT_fno_builtin_)) {
+ A->claim();
// If -fno-builtin is specified, then there's no need to pass the option to
// the frontend.
- if (!UseBuiltins)
- continue;
-
- StringRef FuncName = Arg->getValue();
- CmdArgs.push_back(Args.MakeArgString("-fno-builtin-" + FuncName));
+ if (UseBuiltins)
+ A->render(Args, CmdArgs);
}
// le32-specific flags:
@@ -3397,6 +3745,11 @@ static void RenderBuiltinOptions(const ToolChain &TC, const llvm::Triple &T,
}
bool Driver::getDefaultModuleCachePath(SmallVectorImpl<char> &Result) {
+ if (const char *Str = std::getenv("CLANG_MODULE_CACHE_PATH")) {
+ Twine Path{Str};
+ Path.toVector(Result);
+ return Path.getSingleStringRef() != "";
+ }
if (llvm::sys::path::cache_directory(Result)) {
llvm::sys::path::append(Result, "clang");
llvm::sys::path::append(Result, "ModuleCache");
@@ -3405,10 +3758,14 @@ bool Driver::getDefaultModuleCachePath(SmallVectorImpl<char> &Result) {
return false;
}
-static void RenderModulesOptions(Compilation &C, const Driver &D,
+static bool RenderModulesOptions(Compilation &C, const Driver &D,
const ArgList &Args, const InputInfo &Input,
- const InputInfo &Output,
- ArgStringList &CmdArgs, bool &HaveModules) {
+ const InputInfo &Output, bool HaveStd20,
+ ArgStringList &CmdArgs) {
+ bool IsCXX = types::isCXX(Input.getType());
+ bool HaveStdCXXModules = IsCXX && HaveStd20;
+ bool HaveModules = HaveStdCXXModules;
+
// -fmodules enables the use of precompiled modules (off by default).
// Users can pass -fno-cxx-modules to turn off modules support for
// C++/Objective-C++ programs.
@@ -3416,17 +3773,13 @@ static void RenderModulesOptions(Compilation &C, const Driver &D,
if (Args.hasFlag(options::OPT_fmodules, options::OPT_fno_modules, false)) {
bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules,
options::OPT_fno_cxx_modules, true);
- if (AllowedInCXX || !types::isCXX(Input.getType())) {
+ if (AllowedInCXX || !IsCXX) {
CmdArgs.push_back("-fmodules");
HaveClangModules = true;
}
}
HaveModules |= HaveClangModules;
- if (Args.hasArg(options::OPT_fmodules_ts)) {
- CmdArgs.push_back("-fmodules-ts");
- HaveModules = true;
- }
// -fmodule-maps enables implicit reading of module map files. By default,
// this is enabled if we are using Clang's flavor of precompiled modules.
@@ -3435,9 +3788,8 @@ static void RenderModulesOptions(Compilation &C, const Driver &D,
CmdArgs.push_back("-fimplicit-module-maps");
// -fmodules-decluse checks that modules used are declared so (off by default)
- if (Args.hasFlag(options::OPT_fmodules_decluse,
- options::OPT_fno_modules_decluse, false))
- CmdArgs.push_back("-fmodules-decluse");
+ Args.addOptInFlag(CmdArgs, options::OPT_fmodules_decluse,
+ options::OPT_fno_modules_decluse);
// -fmodules-strict-decluse is like -fmodule-decluse, but also checks that
// all #included headers are part of modules.
@@ -3481,12 +3833,6 @@ static void RenderModulesOptions(Compilation &C, const Driver &D,
}
if (HaveModules) {
- // -fprebuilt-module-path specifies where to load the prebuilt module files.
- for (const Arg *A : Args.filtered(options::OPT_fprebuilt_module_path)) {
- CmdArgs.push_back(Args.MakeArgString(
- std::string("-fprebuilt-module-path=") + A->getValue()));
- A->claim();
- }
if (Args.hasFlag(options::OPT_fprebuilt_implicit_modules,
options::OPT_fno_prebuilt_implicit_modules, false))
CmdArgs.push_back("-fprebuilt-implicit-modules");
@@ -3519,9 +3865,16 @@ static void RenderModulesOptions(Compilation &C, const Driver &D,
// names to precompiled module files (the module is loaded only if used).
// The -fmodule-file=<file> form can be used to unconditionally load
// precompiled module files (whether used or not).
- if (HaveModules)
+ if (HaveModules || Input.getType() == clang::driver::types::TY_ModuleFile) {
Args.AddAllArgs(CmdArgs, options::OPT_fmodule_file);
- else
+
+ // -fprebuilt-module-path specifies where to load the prebuilt module files.
+ for (const Arg *A : Args.filtered(options::OPT_fprebuilt_module_path)) {
+ CmdArgs.push_back(Args.MakeArgString(
+ std::string("-fprebuilt-module-path=") + A->getValue()));
+ A->claim();
+ }
+ } else
Args.ClaimAllArgs(options::OPT_fmodule_file);
// When building modules and generating crashdumps, we need to dump a module
@@ -3545,38 +3898,59 @@ static void RenderModulesOptions(Compilation &C, const Driver &D,
Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_interval);
Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_after);
- Args.AddLastArg(CmdArgs, options::OPT_fbuild_session_timestamp);
+ if (HaveClangModules) {
+ Args.AddLastArg(CmdArgs, options::OPT_fbuild_session_timestamp);
- if (Arg *A = Args.getLastArg(options::OPT_fbuild_session_file)) {
- if (Args.hasArg(options::OPT_fbuild_session_timestamp))
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << A->getAsString(Args) << "-fbuild-session-timestamp";
+ if (Arg *A = Args.getLastArg(options::OPT_fbuild_session_file)) {
+ if (Args.hasArg(options::OPT_fbuild_session_timestamp))
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << A->getAsString(Args) << "-fbuild-session-timestamp";
- 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())));
- }
+ 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)std::chrono::duration_cast<std::chrono::seconds>(
+ Status.getLastModificationTime().time_since_epoch())
+ .count())));
+ }
- if (Args.getLastArg(options::OPT_fmodules_validate_once_per_build_session)) {
- if (!Args.getLastArg(options::OPT_fbuild_session_timestamp,
- options::OPT_fbuild_session_file))
- D.Diag(diag::err_drv_modules_validate_once_requires_timestamp);
+ if (Args.getLastArg(
+ options::OPT_fmodules_validate_once_per_build_session)) {
+ if (!Args.getLastArg(options::OPT_fbuild_session_timestamp,
+ options::OPT_fbuild_session_file))
+ D.Diag(diag::err_drv_modules_validate_once_requires_timestamp);
+
+ Args.AddLastArg(CmdArgs,
+ options::OPT_fmodules_validate_once_per_build_session);
+ }
+
+ if (Args.hasFlag(options::OPT_fmodules_validate_system_headers,
+ options::OPT_fno_modules_validate_system_headers,
+ ImplicitModules))
+ CmdArgs.push_back("-fmodules-validate-system-headers");
Args.AddLastArg(CmdArgs,
- options::OPT_fmodules_validate_once_per_build_session);
+ options::OPT_fmodules_disable_diagnostic_validation);
+ } else {
+ Args.ClaimAllArgs(options::OPT_fbuild_session_timestamp);
+ Args.ClaimAllArgs(options::OPT_fbuild_session_file);
+ Args.ClaimAllArgs(options::OPT_fmodules_validate_once_per_build_session);
+ Args.ClaimAllArgs(options::OPT_fmodules_validate_system_headers);
+ Args.ClaimAllArgs(options::OPT_fno_modules_validate_system_headers);
+ Args.ClaimAllArgs(options::OPT_fmodules_disable_diagnostic_validation);
}
- if (Args.hasFlag(options::OPT_fmodules_validate_system_headers,
- options::OPT_fno_modules_validate_system_headers,
- ImplicitModules))
- CmdArgs.push_back("-fmodules-validate-system-headers");
+ // FIXME: We provisionally don't check ODR violations for decls in the global
+ // module fragment.
+ CmdArgs.push_back("-fskip-odr-check-in-gmf");
- Args.AddLastArg(CmdArgs, options::OPT_fmodules_disable_diagnostic_validation);
+ // Claim `-fmodule-output` and `-fmodule-output=` to avoid unused warnings.
+ Args.ClaimAllArgs(options::OPT_fmodule_output);
+ Args.ClaimAllArgs(options::OPT_fmodule_output_EQ);
+
+ return HaveModules;
}
static void RenderCharacterOptions(const ArgList &Args, const llvm::Triple &T,
@@ -3611,7 +3985,8 @@ static void RenderCharacterOptions(const ArgList &Args, const llvm::Triple &T,
else
CmdArgs.push_back("-fsigned-wchar");
}
- }
+ } else if (T.isOSzOS())
+ CmdArgs.push_back("-fno-signed-wchar");
}
static void RenderObjCOptions(const ToolChain &TC, const Driver &D,
@@ -3736,15 +4111,10 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
options::OPT_fno_caret_diagnostics, CaretDefault))
CmdArgs.push_back("-fno-caret-diagnostics");
- // -fdiagnostics-fixit-info is default, only pass non-default.
- if (!Args.hasFlag(options::OPT_fdiagnostics_fixit_info,
- options::OPT_fno_diagnostics_fixit_info))
- CmdArgs.push_back("-fno-diagnostics-fixit-info");
-
- // Enable -fdiagnostics-show-option by default.
- if (!Args.hasFlag(options::OPT_fdiagnostics_show_option,
- options::OPT_fno_diagnostics_show_option, true))
- CmdArgs.push_back("-fno-diagnostics-show-option");
+ Args.addOptOutFlag(CmdArgs, options::OPT_fdiagnostics_fixit_info,
+ options::OPT_fno_diagnostics_fixit_info);
+ Args.addOptOutFlag(CmdArgs, options::OPT_fdiagnostics_show_option,
+ options::OPT_fno_diagnostics_show_option);
if (const Arg *A =
Args.getLastArg(options::OPT_fdiagnostics_show_category_EQ)) {
@@ -3752,9 +4122,8 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
CmdArgs.push_back(A->getValue());
}
- if (Args.hasFlag(options::OPT_fdiagnostics_show_hotness,
- options::OPT_fno_diagnostics_show_hotness, false))
- CmdArgs.push_back("-fdiagnostics-show-hotness");
+ Args.addOptInFlag(CmdArgs, options::OPT_fdiagnostics_show_hotness,
+ options::OPT_fno_diagnostics_show_hotness);
if (const Arg *A =
Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {
@@ -3763,9 +4132,19 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
CmdArgs.push_back(Args.MakeArgString(Opt));
}
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_fdiagnostics_misexpect_tolerance_EQ)) {
+ std::string Opt =
+ std::string("-fdiagnostics-misexpect-tolerance=") + A->getValue();
+ CmdArgs.push_back(Args.MakeArgString(Opt));
+ }
+
if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) {
CmdArgs.push_back("-fdiagnostics-format");
CmdArgs.push_back(A->getValue());
+ if (StringRef(A->getValue()) == "sarif" ||
+ StringRef(A->getValue()) == "SARIF")
+ D.Diag(diag::warn_drv_sarif_format_unstable);
}
if (const Arg *A = Args.getLastArg(
@@ -3782,22 +4161,13 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
// re-parsed to construct this job; claim any possible color diagnostic here
// to avoid warn_drv_unused_argument and diagnose bad
// OPT_fdiagnostics_color_EQ values.
- for (const Arg *A : Args) {
- const Option &O = A->getOption();
- if (!O.matches(options::OPT_fcolor_diagnostics) &&
- !O.matches(options::OPT_fdiagnostics_color) &&
- !O.matches(options::OPT_fno_color_diagnostics) &&
- !O.matches(options::OPT_fno_diagnostics_color) &&
- !O.matches(options::OPT_fdiagnostics_color_EQ))
- continue;
-
- if (O.matches(options::OPT_fdiagnostics_color_EQ)) {
- StringRef Value(A->getValue());
- if (Value != "always" && Value != "never" && Value != "auto")
- D.Diag(diag::err_drv_clang_unsupported)
- << ("-fdiagnostics-color=" + Value).str();
- }
- A->claim();
+ Args.getLastArg(options::OPT_fcolor_diagnostics,
+ options::OPT_fno_color_diagnostics);
+ if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_color_EQ)) {
+ StringRef Value(A->getValue());
+ if (Value != "always" && Value != "never" && Value != "auto")
+ D.Diag(diag::err_drv_invalid_argument_to_option)
+ << Value << A->getOption().getName();
}
if (D.getDiags().getDiagnosticOptions().ShowColors)
@@ -3806,9 +4176,11 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
if (Args.hasArg(options::OPT_fansi_escape_codes))
CmdArgs.push_back("-fansi-escape-codes");
- if (!Args.hasFlag(options::OPT_fshow_source_location,
- options::OPT_fno_show_source_location))
- CmdArgs.push_back("-fno-show-source-location");
+ Args.addOptOutFlag(CmdArgs, options::OPT_fshow_source_location,
+ options::OPT_fno_show_source_location);
+
+ Args.addOptOutFlag(CmdArgs, options::OPT_fdiagnostics_show_line_numbers,
+ options::OPT_fno_diagnostics_show_line_numbers);
if (Args.hasArg(options::OPT_fdiagnostics_absolute_paths))
CmdArgs.push_back("-fdiagnostics-absolute-paths");
@@ -3817,14 +4189,11 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
ColumnDefault))
CmdArgs.push_back("-fno-show-column");
- if (!Args.hasFlag(options::OPT_fspell_checking,
- options::OPT_fno_spell_checking))
- CmdArgs.push_back("-fno-spell-checking");
+ Args.addOptOutFlag(CmdArgs, options::OPT_fspell_checking,
+ options::OPT_fno_spell_checking);
}
-enum class DwarfFissionKind { None, Split, Single };
-
-static DwarfFissionKind getDebugFissionKind(const Driver &D,
+DwarfFissionKind tools::getDebugFissionKind(const Driver &D,
const ArgList &Args, Arg *&Arg) {
Arg = Args.getLastArg(options::OPT_gsplit_dwarf, options::OPT_gsplit_dwarf_EQ,
options::OPT_gno_split_dwarf);
@@ -3841,7 +4210,7 @@ static DwarfFissionKind getDebugFissionKind(const Driver &D,
return DwarfFissionKind::Single;
D.Diag(diag::err_drv_unsupported_option_argument)
- << Arg->getOption().getName() << Arg->getValue();
+ << Arg->getSpelling() << Arg->getValue();
return DwarfFissionKind::None;
}
@@ -3868,18 +4237,12 @@ static void renderDwarfFormat(const Driver &D, const llvm::Triple &T,
DwarfFormatArg->render(Args, CmdArgs);
}
-static void renderDebugOptions(const ToolChain &TC, const Driver &D,
- const llvm::Triple &T, const ArgList &Args,
- bool EmitCodeView, bool IRInput,
- 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);
-
+static void
+renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T,
+ const ArgList &Args, bool IRInput, ArgStringList &CmdArgs,
+ const InputInfo &Output,
+ llvm::codegenoptions::DebugInfoKind &DebugInfoKind,
+ DwarfFissionKind &DwarfFission) {
if (Args.hasFlag(options::OPT_fdebug_info_for_profiling,
options::OPT_fno_debug_info_for_profiling, false) &&
checkDebugInfoOption(
@@ -3914,27 +4277,29 @@ static void renderDebugOptions(const ToolChain &TC, const Driver &D,
}
}
if (const Arg *A = Args.getLastArg(options::OPT_g_Group)) {
- DebugInfoKind = codegenoptions::DebugInfoConstructor;
+ DebugInfoKind = llvm::codegenoptions::DebugInfoConstructor;
// If the last option explicitly specified a debug-info level, use it.
if (checkDebugInfoOption(A, Args, D, TC) &&
A->getOption().matches(options::OPT_gN_Group)) {
- DebugInfoKind = DebugLevelToInfoKind(*A);
+ DebugInfoKind = debugLevelToInfoKind(*A);
// For -g0 or -gline-tables-only, drop -gsplit-dwarf. This gets a bit more
// complicated if you've disabled inline info in the skeleton CUs
// (SplitDWARFInlining) - then there's value in composing split-dwarf and
// line-tables-only, so let those compose naturally in that case.
- if (DebugInfoKind == codegenoptions::NoDebugInfo ||
- DebugInfoKind == codegenoptions::DebugDirectivesOnly ||
- (DebugInfoKind == codegenoptions::DebugLineTablesOnly &&
+ if (DebugInfoKind == llvm::codegenoptions::NoDebugInfo ||
+ DebugInfoKind == llvm::codegenoptions::DebugDirectivesOnly ||
+ (DebugInfoKind == llvm::codegenoptions::DebugLineTablesOnly &&
SplitDWARFInlining))
DwarfFission = DwarfFissionKind::None;
}
}
// If a debugger tuning argument appeared, remember it.
+ bool HasDebuggerTuning = false;
if (const Arg *A =
Args.getLastArg(options::OPT_gTune_Group, options::OPT_ggdbN_Group)) {
+ HasDebuggerTuning = true;
if (checkDebugInfoOption(A, Args, D, TC)) {
if (A->getOption().matches(options::OPT_glldb))
DebuggerTuning = llvm::DebuggerKind::LLDB;
@@ -3948,29 +4313,23 @@ static void renderDebugOptions(const ToolChain &TC, const Driver &D,
}
// If a -gdwarf argument appeared, remember it.
- const Arg *GDwarfN = getDwarfNArg(Args);
bool EmitDwarf = false;
- if (GDwarfN) {
- if (checkDebugInfoOption(GDwarfN, Args, D, TC))
- EmitDwarf = true;
- else
- GDwarfN = nullptr;
- }
+ if (const Arg *A = getDwarfNArg(Args))
+ EmitDwarf = checkDebugInfoOption(A, Args, D, TC);
- if (const Arg *A = Args.getLastArg(options::OPT_gcodeview)) {
- if (checkDebugInfoOption(A, Args, D, TC))
- EmitCodeView = true;
- }
+ bool EmitCodeView = false;
+ if (const Arg *A = Args.getLastArg(options::OPT_gcodeview))
+ EmitCodeView = checkDebugInfoOption(A, Args, D, TC);
// If the user asked for debug info but did not explicitly specify -gcodeview
// or -gdwarf, ask the toolchain for the default format.
if (!EmitCodeView && !EmitDwarf &&
- DebugInfoKind != codegenoptions::NoDebugInfo) {
+ DebugInfoKind != llvm::codegenoptions::NoDebugInfo) {
switch (TC.getDefaultDebugFormat()) {
- case codegenoptions::DIF_CodeView:
+ case llvm::codegenoptions::DIF_CodeView:
EmitCodeView = true;
break;
- case codegenoptions::DIF_DWARF:
+ case llvm::codegenoptions::DIF_DWARF:
EmitDwarf = true;
break;
}
@@ -3979,31 +4338,19 @@ static void renderDebugOptions(const ToolChain &TC, const Driver &D,
unsigned RequestedDWARFVersion = 0; // DWARF version requested by the user
unsigned EffectiveDWARFVersion = 0; // DWARF version TC can generate. It may
// be lower than what the user wanted.
- unsigned DefaultDWARFVersion = ParseDebugDefaultVersion(TC, Args);
if (EmitDwarf) {
- // Start with the platform default DWARF version
- RequestedDWARFVersion = TC.GetDefaultDwarfVersion();
- assert(RequestedDWARFVersion &&
- "toolchain default DWARF version must be nonzero");
-
- // If the user specified a default DWARF version, that takes precedence
- // over the platform default.
- if (DefaultDWARFVersion)
- RequestedDWARFVersion = DefaultDWARFVersion;
-
- // Override with a user-specified DWARF version
- if (GDwarfN)
- if (auto ExplicitVersion = DwarfVersionNum(GDwarfN->getSpelling()))
- RequestedDWARFVersion = ExplicitVersion;
+ RequestedDWARFVersion = getDwarfVersion(TC, Args);
// Clamp effective DWARF version to the max supported by the toolchain.
EffectiveDWARFVersion =
std::min(RequestedDWARFVersion, TC.getMaxDwarfVersion());
+ } else {
+ Args.ClaimAllArgs(options::OPT_fdebug_default_version);
}
// -gline-directives-only supported only for the DWARF debug info.
if (RequestedDWARFVersion == 0 &&
- DebugInfoKind == codegenoptions::DebugDirectivesOnly)
- DebugInfoKind = codegenoptions::NoDebugInfo;
+ DebugInfoKind == llvm::codegenoptions::DebugDirectivesOnly)
+ DebugInfoKind = llvm::codegenoptions::NoDebugInfo;
// strict DWARF is set to false by default. But for DBX, we need it to be set
// as true by default.
@@ -4031,16 +4378,19 @@ static void renderDebugOptions(const ToolChain &TC, const Driver &D,
CmdArgs.push_back("-gno-column-info");
// FIXME: Move backend command line options to the module.
- // If -gline-tables-only or -gline-directives-only is the last option it wins.
- if (const Arg *A = Args.getLastArg(options::OPT_gmodules))
- if (checkDebugInfoOption(A, Args, D, TC)) {
- if (DebugInfoKind != codegenoptions::DebugLineTablesOnly &&
- DebugInfoKind != codegenoptions::DebugDirectivesOnly) {
- DebugInfoKind = codegenoptions::DebugInfoConstructor;
+ if (Args.hasFlag(options::OPT_gmodules, options::OPT_gno_modules, false)) {
+ // If -gline-tables-only or -gline-directives-only is the last option it
+ // wins.
+ if (checkDebugInfoOption(Args.getLastArg(options::OPT_gmodules), Args, D,
+ TC)) {
+ if (DebugInfoKind != llvm::codegenoptions::DebugLineTablesOnly &&
+ DebugInfoKind != llvm::codegenoptions::DebugDirectivesOnly) {
+ DebugInfoKind = llvm::codegenoptions::DebugInfoConstructor;
CmdArgs.push_back("-dwarf-ext-refs");
CmdArgs.push_back("-fmodule-format=obj");
}
}
+ }
if (T.isOSBinFormatELF() && SplitDWARFInlining)
CmdArgs.push_back("-fsplit-dwarf-inlining");
@@ -4057,13 +4407,13 @@ static void renderDebugOptions(const ToolChain &TC, const Driver &D,
if (const Arg *A = Args.getLastArg(options::OPT_fstandalone_debug))
(void)checkDebugInfoOption(A, Args, D, TC);
- if (DebugInfoKind == codegenoptions::LimitedDebugInfo ||
- DebugInfoKind == codegenoptions::DebugInfoConstructor) {
+ if (DebugInfoKind == llvm::codegenoptions::LimitedDebugInfo ||
+ DebugInfoKind == llvm::codegenoptions::DebugInfoConstructor) {
if (Args.hasFlag(options::OPT_fno_eliminate_unused_debug_types,
options::OPT_feliminate_unused_debug_types, false))
- DebugInfoKind = codegenoptions::UnusedTypeInfo;
+ DebugInfoKind = llvm::codegenoptions::UnusedTypeInfo;
else if (NeedFullDebug)
- DebugInfoKind = codegenoptions::FullDebugInfo;
+ DebugInfoKind = llvm::codegenoptions::FullDebugInfo;
}
if (Args.hasFlag(options::OPT_gembed_source, options::OPT_gno_embed_source,
@@ -4089,29 +4439,30 @@ static void renderDebugOptions(const ToolChain &TC, const Driver &D,
if (EmitCodeView) {
CmdArgs.push_back("-gcodeview");
- // Emit codeview type hashes if requested.
- if (Args.hasFlag(options::OPT_gcodeview_ghash,
- options::OPT_gno_codeview_ghash, false)) {
- CmdArgs.push_back("-gcodeview-ghash");
- }
- }
+ Args.addOptInFlag(CmdArgs, options::OPT_gcodeview_ghash,
+ options::OPT_gno_codeview_ghash);
- // Omit inline line tables if requested.
- if (Args.hasFlag(options::OPT_gno_inline_line_tables,
- options::OPT_ginline_line_tables, false)) {
- CmdArgs.push_back("-gno-inline-line-tables");
+ Args.addOptOutFlag(CmdArgs, options::OPT_gcodeview_command_line,
+ options::OPT_gno_codeview_command_line);
}
+ Args.addOptOutFlag(CmdArgs, options::OPT_ginline_line_tables,
+ options::OPT_gno_inline_line_tables);
+
// When emitting remarks, we need at least debug lines in the output.
if (willEmitRemarks(Args) &&
- DebugInfoKind <= codegenoptions::DebugDirectivesOnly)
- DebugInfoKind = codegenoptions::DebugLineTablesOnly;
+ DebugInfoKind <= llvm::codegenoptions::DebugDirectivesOnly)
+ DebugInfoKind = llvm::codegenoptions::DebugLineTablesOnly;
// Adjust the debug info kind for the given toolchain.
TC.adjustDebugInfoKind(DebugInfoKind, Args);
+ // On AIX, the debugger tuning option can be omitted if it is not explicitly
+ // set.
RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, EffectiveDWARFVersion,
- DebuggerTuning);
+ T.isOSAIX() && !HasDebuggerTuning
+ ? llvm::DebuggerKind::Default
+ : DebuggerTuning);
// -fdebug-macro turns on macro debug info generation.
if (Args.hasFlag(options::OPT_fdebug_macro, options::OPT_fno_debug_macro,
@@ -4133,12 +4484,27 @@ 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);
+ 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");
+ }
+ }
- if (Args.hasFlag(options::OPT_fdebug_ranges_base_address,
- options::OPT_fno_debug_ranges_base_address, false)) {
- CmdArgs.push_back("-fdebug-ranges-base-address");
+ if (const Arg *A = Args.getLastArg(options::OPT_gsrc_hash_EQ)) {
+ StringRef v = A->getValue();
+ CmdArgs.push_back(Args.MakeArgString("-gsrc-hash=" + v));
}
+ Args.addOptInFlag(CmdArgs, options::OPT_fdebug_ranges_base_address,
+ options::OPT_fno_debug_ranges_base_address);
+
// -gdwarf-aranges turns on the emission of the aranges section in the
// backend.
// Always enabled for SCE tuning.
@@ -4150,9 +4516,8 @@ static void renderDebugOptions(const ToolChain &TC, const Driver &D,
CmdArgs.push_back("-generate-arange-section");
}
- if (Args.hasFlag(options::OPT_fforce_dwarf_frame,
- options::OPT_fno_force_dwarf_frame, false))
- CmdArgs.push_back("-fforce-dwarf-frame");
+ Args.addOptInFlag(CmdArgs, options::OPT_fforce_dwarf_frame,
+ options::OPT_fno_force_dwarf_frame);
if (Args.hasFlag(options::OPT_fdebug_types_section,
options::OPT_fno_debug_types_section, false)) {
@@ -4179,7 +4544,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
@@ -4189,6 +4554,98 @@ static void renderDebugOptions(const ToolChain &TC, const Driver &D,
renderDwarfFormat(D, T, Args, CmdArgs, EffectiveDWARFVersion);
RenderDebugInfoCompressionArgs(Args, CmdArgs, D, TC);
+
+ // This controls whether or not we perform JustMyCode instrumentation.
+ if (Args.hasFlag(options::OPT_fjmc, options::OPT_fno_jmc, false)) {
+ if (TC.getTriple().isOSBinFormatELF() || D.IsCLMode()) {
+ if (DebugInfoKind >= llvm::codegenoptions::DebugInfoConstructor)
+ CmdArgs.push_back("-fjmc");
+ else if (D.IsCLMode())
+ D.Diag(clang::diag::warn_drv_jmc_requires_debuginfo) << "/JMC"
+ << "'/Zi', '/Z7'";
+ else
+ D.Diag(clang::diag::warn_drv_jmc_requires_debuginfo) << "-fjmc"
+ << "-g";
+ } else {
+ D.Diag(clang::diag::warn_drv_fjmc_for_elf_only);
+ }
+ }
+
+ // Add in -fdebug-compilation-dir if necessary.
+ const char *DebugCompilationDir =
+ addDebugCompDirArg(Args, CmdArgs, D.getVFS());
+
+ addDebugPrefixMapArg(D, TC, Args, CmdArgs);
+
+ // Add the output path to the object file for CodeView debug infos.
+ if (EmitCodeView && Output.isFilename())
+ addDebugObjectName(Args, CmdArgs, DebugCompilationDir,
+ Output.getFilename());
+}
+
+static void ProcessVSRuntimeLibrary(const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ unsigned RTOptionID = options::OPT__SLASH_MT;
+
+ if (Args.hasArg(options::OPT__SLASH_LDd))
+ // The /LDd option implies /MTd. The dependent lib part can be overridden,
+ // but defining _DEBUG is sticky.
+ RTOptionID = options::OPT__SLASH_MTd;
+
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_M_Group))
+ RTOptionID = A->getOption().getID();
+
+ if (Arg *A = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
+ RTOptionID = llvm::StringSwitch<unsigned>(A->getValue())
+ .Case("static", options::OPT__SLASH_MT)
+ .Case("static_dbg", options::OPT__SLASH_MTd)
+ .Case("dll", options::OPT__SLASH_MD)
+ .Case("dll_dbg", options::OPT__SLASH_MDd)
+ .Default(options::OPT__SLASH_MT);
+ }
+
+ StringRef FlagForCRT;
+ switch (RTOptionID) {
+ case options::OPT__SLASH_MD:
+ if (Args.hasArg(options::OPT__SLASH_LDd))
+ CmdArgs.push_back("-D_DEBUG");
+ CmdArgs.push_back("-D_MT");
+ CmdArgs.push_back("-D_DLL");
+ FlagForCRT = "--dependent-lib=msvcrt";
+ break;
+ case options::OPT__SLASH_MDd:
+ CmdArgs.push_back("-D_DEBUG");
+ CmdArgs.push_back("-D_MT");
+ CmdArgs.push_back("-D_DLL");
+ FlagForCRT = "--dependent-lib=msvcrtd";
+ break;
+ case options::OPT__SLASH_MT:
+ if (Args.hasArg(options::OPT__SLASH_LDd))
+ CmdArgs.push_back("-D_DEBUG");
+ CmdArgs.push_back("-D_MT");
+ CmdArgs.push_back("-flto-visibility-public-std");
+ FlagForCRT = "--dependent-lib=libcmt";
+ break;
+ case options::OPT__SLASH_MTd:
+ CmdArgs.push_back("-D_DEBUG");
+ CmdArgs.push_back("-D_MT");
+ CmdArgs.push_back("-flto-visibility-public-std");
+ FlagForCRT = "--dependent-lib=libcmtd";
+ break;
+ default:
+ llvm_unreachable("Unexpected option ID.");
+ }
+
+ if (Args.hasArg(options::OPT_fms_omit_default_lib)) {
+ CmdArgs.push_back("-D_VC_NODEFAULTLIB");
+ } else {
+ CmdArgs.push_back(FlagForCRT.data());
+
+ // This provides POSIX compatibility (maps 'open' to '_open'), which most
+ // users want. The /Za flag to cl.exe turns this off, but it's not
+ // implemented in clang.
+ CmdArgs.push_back("--dependent-lib=oldnames");
+ }
}
void Clang::ConstructJob(Compilation &C, const JobAction &JA,
@@ -4204,50 +4661,57 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const Driver &D = TC.getDriver();
ArgStringList CmdArgs;
- // Check number of inputs for sanity. We need at least one input.
assert(Inputs.size() >= 1 && "Must have at least one input.");
// CUDA/HIP compilation may have multiple inputs (source file + results of
// device-side compilations). OpenMP device jobs also take the host IR as a
// second input. Module precompilation accepts a list of header files to
- // include as part of the module. All other jobs are expected to have exactly
- // one input.
+ // include as part of the module. API extraction accepts a list of header
+ // files whose API information is emitted in the output. All other jobs are
+ // expected to have exactly one input.
bool IsCuda = JA.isOffloading(Action::OFK_Cuda);
bool IsCudaDevice = JA.isDeviceOffloading(Action::OFK_Cuda);
bool IsHIP = JA.isOffloading(Action::OFK_HIP);
bool IsHIPDevice = JA.isDeviceOffloading(Action::OFK_HIP);
bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP);
- bool IsHeaderModulePrecompile = isa<HeaderModulePrecompileJobAction>(JA);
+ bool IsExtractAPI = isa<ExtractAPIJobAction>(JA);
bool IsDeviceOffloadAction = !(JA.isDeviceOffloading(Action::OFK_None) ||
JA.isDeviceOffloading(Action::OFK_Host));
+ bool IsHostOffloadingAction =
+ JA.isHostOffloading(Action::OFK_OpenMP) ||
+ (JA.isHostOffloading(C.getActiveOffloadKinds()) &&
+ Args.hasFlag(options::OPT_offload_new_driver,
+ options::OPT_no_offload_new_driver, false));
+
+ bool IsRDCMode =
+ Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false);
bool IsUsingLTO = D.isUsingLTO(IsDeviceOffloadAction);
auto LTOMode = D.getLTOMode(IsDeviceOffloadAction);
- // A header module compilation doesn't have a main input file, so invent a
- // fake one as a placeholder.
- const char *ModuleName = [&]{
- auto *ModuleNameArg = Args.getLastArg(options::OPT_fmodule_name_EQ);
- return ModuleNameArg ? ModuleNameArg->getValue() : "";
- }();
- InputInfo HeaderModuleInput(Inputs[0].getType(), ModuleName, ModuleName);
+ // Extract API doesn't have a main input file, so invent a fake one as a
+ // placeholder.
+ InputInfo ExtractAPIPlaceholderInput(Inputs[0].getType(), "extract-api",
+ "extract-api");
const InputInfo &Input =
- IsHeaderModulePrecompile ? HeaderModuleInput : Inputs[0];
+ IsExtractAPI ? ExtractAPIPlaceholderInput : Inputs[0];
- InputInfoList ModuleHeaderInputs;
+ InputInfoList ExtractAPIInputs;
+ InputInfoList HostOffloadingInputs;
const InputInfo *CudaDeviceInput = nullptr;
const InputInfo *OpenMPDeviceInput = nullptr;
for (const InputInfo &I : Inputs) {
- if (&I == &Input) {
- // This is the primary input.
- } else if (IsHeaderModulePrecompile &&
- types::getPrecompiledType(I.getType()) == types::TY_PCH) {
- types::ID Expected = HeaderModuleInput.getType();
- if (I.getType() != Expected) {
- D.Diag(diag::err_drv_module_header_wrong_kind)
+ if (&I == &Input || I.getType() == types::TY_Nothing) {
+ // This is the primary input or contains nothing.
+ } else if (IsExtractAPI) {
+ auto ExpectedInputType = ExtractAPIPlaceholderInput.getType();
+ if (I.getType() != ExpectedInputType) {
+ D.Diag(diag::err_drv_extract_api_wrong_kind)
<< I.getFilename() << types::getTypeName(I.getType())
- << types::getTypeName(Expected);
+ << types::getTypeName(ExpectedInputType);
}
- ModuleHeaderInputs.push_back(I);
+ ExtractAPIInputs.push_back(I);
+ } else if (IsHostOffloadingAction) {
+ HostOffloadingInputs.push_back(I);
} else if ((IsCuda || IsHIP) && !CudaDeviceInput) {
CudaDeviceInput = &I;
} else if (IsOpenMPDevice && !OpenMPDeviceInput) {
@@ -4317,12 +4781,36 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(
Twine("-target-sdk-version=") +
CudaVersionToString(CTC->CudaInstallation.version())));
+ // Unsized function arguments used for variadics were introduced in
+ // CUDA-9.0. We still do not support generating code that actually uses
+ // variadic arguments yet, but we do need to allow parsing them as
+ // recent CUDA headers rely on that.
+ // https://github.com/llvm/llvm-project/issues/58410
+ if (CTC->CudaInstallation.version() >= CudaVersion::CUDA_90)
+ CmdArgs.push_back("-fcuda-allow-variadic-functions");
}
}
CmdArgs.push_back("-aux-triple");
CmdArgs.push_back(Args.MakeArgString(NormalizedTriple));
+
+ if (JA.isDeviceOffloading(Action::OFK_HIP) &&
+ getToolChain().getTriple().isAMDGPU()) {
+ // Device side compilation printf
+ if (Args.getLastArg(options::OPT_mprintf_kind_EQ)) {
+ CmdArgs.push_back(Args.MakeArgString(
+ "-mprintf-kind=" +
+ Args.getLastArgValue(options::OPT_mprintf_kind_EQ)));
+ // Force compiler error on invalid conversion specifiers
+ CmdArgs.push_back(
+ Args.MakeArgString("-Werror=format-invalid-specifier"));
+ }
+ }
}
+ // Unconditionally claim the printf option now to avoid unused diagnostic.
+ if (const Arg *PF = Args.getLastArg(options::OPT_mprintf_kind_EQ))
+ PF->claim();
+
if (Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false)) {
CmdArgs.push_back("-fsycl-is-device");
@@ -4361,12 +4849,20 @@ 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.
RewriteKind rewriteKind = RK_None;
+ bool UnifiedLTO = false;
+ if (IsUsingLTO) {
+ UnifiedLTO = Args.hasFlag(options::OPT_funified_lto,
+ options::OPT_fno_unified_lto, Triple.isPS());
+ if (UnifiedLTO)
+ CmdArgs.push_back("-funified-lto");
+ }
+
// If CollectArgsForIntegratedAssembler() isn't called below, claim the args
// it claims when not running an assembler. Otherwise, clang would emit
// "argument unused" warnings for assembler flags when e.g. adding "-E" to
@@ -4395,6 +4891,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
Args.ClaimAllArgs(options::OPT_Wa_COMMA);
Args.ClaimAllArgs(options::OPT_Xassembler);
+ Args.ClaimAllArgs(options::OPT_femit_dwarf_unwind_EQ);
}
if (isa<AnalyzeJobAction>(JA)) {
@@ -4410,6 +4907,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_rewrite_objc) &&
!Args.hasArg(options::OPT_g_Group))
CmdArgs.push_back("-P");
+ else if (JA.getType() == types::TY_PP_CXXHeaderUnit)
+ CmdArgs.push_back("-fdirectives-only");
}
} else if (isa<AssembleJobAction>(JA)) {
CmdArgs.push_back("-emit-obj");
@@ -4422,13 +4921,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (JA.getType() == types::TY_Nothing)
CmdArgs.push_back("-fsyntax-only");
else if (JA.getType() == types::TY_ModuleFile)
- CmdArgs.push_back(IsHeaderModulePrecompile
- ? "-emit-header-module"
- : "-emit-module-interface");
+ CmdArgs.push_back("-emit-module-interface");
+ else if (JA.getType() == types::TY_HeaderUnit)
+ CmdArgs.push_back("-emit-header-unit");
else
CmdArgs.push_back("-emit-pch");
} else if (isa<VerifyPCHJobAction>(JA)) {
CmdArgs.push_back("-verify-pch");
+ } else if (isa<ExtractAPIJobAction>(JA)) {
+ assert(JA.getType() == types::TY_API_INFO &&
+ "Extract API actions must generate a API information.");
+ CmdArgs.push_back("-extract-api");
+ if (Arg *ProductNameArg = Args.getLastArg(options::OPT_product_name_EQ))
+ ProductNameArg->render(Args, CmdArgs);
+ if (Arg *ExtractAPIIgnoresFileArg =
+ Args.getLastArg(options::OPT_extract_api_ignores_EQ))
+ ExtractAPIIgnoresFileArg->render(Args, CmdArgs);
} else {
assert((isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) &&
"Invalid action for clang tool.");
@@ -4479,38 +4987,47 @@ 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 {
+ if (IsDeviceOffloadAction && !JA.isDeviceOffloading(Action::OFK_OpenMP) &&
+ !Args.hasFlag(options::OPT_offload_new_driver,
+ options::OPT_no_offload_new_driver, false) &&
+ !Triple.isAMDGPU()) {
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< Args.getLastArg(options::OPT_foffload_lto,
options::OPT_foffload_lto_EQ)
->getAsString(Args)
<< Triple.getTriple();
+ } else if (Triple.isNVPTX() && !IsRDCMode &&
+ JA.isDeviceOffloading(Action::OFK_Cuda)) {
+ D.Diag(diag::err_drv_unsupported_opt_for_language_mode)
+ << Args.getLastArg(options::OPT_foffload_lto,
+ options::OPT_foffload_lto_EQ)
+ ->getAsString(Args)
+ << "-fno-gpu-rdc";
+ } else {
+ assert(LTOMode == LTOK_Full || LTOMode == LTOK_Thin);
+ CmdArgs.push_back(Args.MakeArgString(
+ Twine("-flto=") + (LTOMode == LTOK_Thin ? "thin" : "full")));
+ // PS4 uses the legacy LTO API, which does not support some of the
+ // features enabled by -flto-unit.
+ if (!RawTriple.isPS4() ||
+ (D.getLTOMode() == LTOK_Full) || !UnifiedLTO)
+ CmdArgs.push_back("-flto-unit");
}
}
}
+ Args.AddLastArg(CmdArgs, options::OPT_dumpdir);
+
if (const Arg *A = Args.getLastArg(options::OPT_fthinlto_index_EQ)) {
if (!types::isLLVMIR(Input.getType()))
D.Diag(diag::err_drv_arg_requires_bitcode_input) << A->getAsString(Args);
Args.AddLastArg(CmdArgs, options::OPT_fthinlto_index_EQ);
}
+ if (Triple.isPPC())
+ Args.addOptInFlag(CmdArgs, options::OPT_mregnames,
+ options::OPT_mno_regnames);
+
if (Args.getLastArg(options::OPT_fthin_link_bitcode_EQ))
Args.AddLastArg(CmdArgs, options::OPT_fthin_link_bitcode_EQ);
@@ -4524,6 +5041,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
!MemProfArg->getOption().matches(options::OPT_fno_memory_profile))
MemProfArg->render(Args, CmdArgs);
+ if (auto *MemProfUseArg =
+ Args.getLastArg(options::OPT_fmemory_profile_use_EQ)) {
+ if (MemProfArg)
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << MemProfUseArg->getAsString(Args) << MemProfArg->getAsString(Args);
+ if (auto *PGOInstrArg = Args.getLastArg(options::OPT_fprofile_generate,
+ options::OPT_fprofile_generate_EQ))
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << MemProfUseArg->getAsString(Args) << PGOInstrArg->getAsString(Args);
+ MemProfUseArg->render(Args, CmdArgs);
+ }
+
// Embed-bitcode option.
// Only white-listed flags below are allowed to be embedded.
if (C.getDriver().embedBitcodeInObject() && !IsUsingLTO &&
@@ -4538,7 +5067,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,
@@ -4582,14 +5111,12 @@ 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.
- if (!Args.hasFlag(options::OPT_foptimize_sibling_calls,
- options::OPT_fno_optimize_sibling_calls))
- CmdArgs.push_back("-mdisable-tail-calls");
+ Args.addOptOutFlag(CmdArgs, options::OPT_foptimize_sibling_calls,
+ options::OPT_fno_optimize_sibling_calls);
RenderFloatingPointOptions(TC, D, isOptimizationLevelFast(Args), Args,
CmdArgs, JA);
@@ -4600,7 +5127,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:
@@ -4639,7 +5166,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(std::make_unique<Command>(
JA, *this, ResponseFileSupport::AtFileUTF8(), D.getClangProgramPath(),
- CmdArgs, Inputs, Output));
+ CmdArgs, Inputs, Output, D.getPrependArg()));
return;
}
@@ -4651,6 +5178,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;
@@ -4658,18 +5186,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const bool IsAssertBuild = true;
#endif
- // Disable the verification pass in -asserts builds.
- if (!IsAssertBuild)
+ // Disable the verification pass in asserts builds unless otherwise specified.
+ if (Args.hasFlag(options::OPT_fno_verify_intermediate_code,
+ options::OPT_fverify_intermediate_code, !IsAssertBuild)) {
CmdArgs.push_back("-disable-llvm-verifier");
+ }
// Discard value names in assert builds unless otherwise specified.
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");
@@ -4699,13 +5228,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Since we can't access frontend flags through hasArg, let's manually iterate
// through them.
bool FoundAnalyzerConfig = false;
- for (auto Arg : Args.filtered(options::OPT_Xclang))
+ for (auto *Arg : Args.filtered(options::OPT_Xclang))
if (StringRef(Arg->getValue()) == "-analyzer-config") {
FoundAnalyzerConfig = true;
break;
}
if (!FoundAnalyzerConfig)
- for (auto Arg : Args.filtered(options::OPT_Xanalyzer))
+ for (auto *Arg : Args.filtered(options::OPT_Xanalyzer))
if (StringRef(Arg->getValue()) == "-analyzer-config") {
FoundAnalyzerConfig = true;
break;
@@ -4722,10 +5251,74 @@ 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))));
+ }
+
+ if (Triple.isOSzOS()) {
+ // On z/OS some of the system header feature macros need to
+ // be defined to enable most cross platform projects to build
+ // successfully. Ths include the libc++ library. A
+ // complicating factor is that users can define these
+ // macros to the same or different values. We need to add
+ // the definition for these macros to the compilation command
+ // if the user hasn't already defined them.
+
+ auto findMacroDefinition = [&](const std::string &Macro) {
+ auto MacroDefs = Args.getAllArgValues(options::OPT_D);
+ return llvm::any_of(MacroDefs, [&](const std::string &M) {
+ return M == Macro || M.find(Macro + '=') != std::string::npos;
+ });
+ };
+
+ // _UNIX03_WITHDRAWN is required for libcxx & porting.
+ if (!findMacroDefinition("_UNIX03_WITHDRAWN"))
+ CmdArgs.push_back("-D_UNIX03_WITHDRAWN");
+ // _OPEN_DEFAULT is required for XL compat
+ if (!findMacroDefinition("_OPEN_DEFAULT"))
+ CmdArgs.push_back("-D_OPEN_DEFAULT");
+ if (D.CCCIsCXX() || types::isCXX(Input.getType())) {
+ // _XOPEN_SOURCE=600 is required for libcxx.
+ if (!findMacroDefinition("_XOPEN_SOURCE"))
+ CmdArgs.push_back("-D_XOPEN_SOURCE=600");
+ }
+ }
+
llvm::Reloc::Model RelocationModel;
unsigned PICLevel;
bool IsPIE;
std::tie(RelocationModel, PICLevel, IsPIE) = ParsePICArgs(TC, Args);
+ Arg *LastPICDataRelArg =
+ Args.getLastArg(options::OPT_mno_pic_data_is_text_relative,
+ options::OPT_mpic_data_is_text_relative);
+ bool NoPICDataIsTextRelative = false;
+ if (LastPICDataRelArg) {
+ if (LastPICDataRelArg->getOption().matches(
+ options::OPT_mno_pic_data_is_text_relative)) {
+ NoPICDataIsTextRelative = true;
+ if (!PICLevel)
+ D.Diag(diag::err_drv_argument_only_allowed_with)
+ << "-mno-pic-data-is-text-relative"
+ << "-fpic/-fpie";
+ }
+ if (!Triple.isSystemZ())
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << (NoPICDataIsTextRelative ? "-mno-pic-data-is-text-relative"
+ : "-mpic-data-is-text-relative")
+ << RawTriple.str();
+ }
bool IsROPI = RelocationModel == llvm::Reloc::ROPI ||
RelocationModel == llvm::Reloc::ROPI_RWPI;
@@ -4754,6 +5347,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(PICLevel == 1 ? "1" : "2");
if (IsPIE)
CmdArgs.push_back("-pic-is-pie");
+ if (NoPICDataIsTextRelative)
+ CmdArgs.push_back("-mcmodel=medium");
}
if (RelocationModel == llvm::Reloc::ROPI ||
@@ -4810,37 +5405,41 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- Args.AddLastArg(CmdArgs, options::OPT_fveclib);
+ if (Arg *A = Args.getLastArg(options::OPT_fveclib)) {
+ StringRef Name = A->getValue();
+ if (Name == "SVML") {
+ if (Triple.getArch() != llvm::Triple::x86 &&
+ Triple.getArch() != llvm::Triple::x86_64)
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << Name << Triple.getArchName();
+ } else if (Name == "LIBMVEC-X86") {
+ if (Triple.getArch() != llvm::Triple::x86 &&
+ Triple.getArch() != llvm::Triple::x86_64)
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << Name << Triple.getArchName();
+ } else if (Name == "SLEEF" || Name == "ArmPL") {
+ if (Triple.getArch() != llvm::Triple::aarch64 &&
+ Triple.getArch() != llvm::Triple::aarch64_be)
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << Name << Triple.getArchName();
+ }
+ A->render(Args, CmdArgs);
+ }
if (Args.hasFlag(options::OPT_fmerge_all_constants,
options::OPT_fno_merge_all_constants, false))
CmdArgs.push_back("-fmerge-all-constants");
- if (Args.hasFlag(options::OPT_fno_delete_null_pointer_checks,
- options::OPT_fdelete_null_pointer_checks, false))
- CmdArgs.push_back("-fno-delete-null-pointer-checks");
+ Args.addOptOutFlag(CmdArgs, options::OPT_fdelete_null_pointer_checks,
+ options::OPT_fno_delete_null_pointer_checks);
// LLVM Code Generator Options.
- for (const Arg *A : Args.filtered(options::OPT_frewrite_map_file_EQ)) {
- StringRef Map = A->getValue();
- if (!llvm::sys::fs::exists(Map)) {
- D.Diag(diag::err_drv_no_such_file) << Map;
- } else {
- A->render(Args, CmdArgs);
- A->claim();
- }
- }
-
- if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ_vec_extabi,
- options::OPT_mabi_EQ_vec_default)) {
- if (!Triple.isOSAIX())
+ if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ_quadword_atomics)) {
+ if (!Triple.isOSAIX() || Triple.isPPC32())
D.Diag(diag::err_drv_unsupported_opt_for_target)
- << A->getSpelling() << RawTriple.str();
- if (A->getOption().getID() == options::OPT_mabi_EQ_vec_extabi)
- CmdArgs.push_back("-mabi=vec-extabi");
- else
- CmdArgs.push_back("-mabi=vec-default");
+ << A->getSpelling() << RawTriple.str();
+ CmdArgs.push_back("-mabi=quadword-atomics");
}
if (Arg *A = Args.getLastArg(options::OPT_mlong_double_128)) {
@@ -4852,27 +5451,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
if (Arg *A = Args.getLastArg(options::OPT_Wframe_larger_than_EQ)) {
- StringRef v = A->getValue();
- // FIXME: Validate the argument here so we don't produce meaningless errors
- // about -fwarn-stack-size=.
- if (v.empty())
- D.Diag(diag::err_drv_missing_argument) << A->getSpelling() << 1;
+ StringRef V = A->getValue(), V1 = V;
+ unsigned Size;
+ if (V1.consumeInteger(10, Size) || !V1.empty())
+ D.Diag(diag::err_drv_invalid_argument_to_option)
+ << V << A->getOption().getName();
else
- CmdArgs.push_back(Args.MakeArgString("-fwarn-stack-size=" + v));
- A->claim();
+ CmdArgs.push_back(Args.MakeArgString("-fwarn-stack-size=" + V));
}
- if (!Args.hasFlag(options::OPT_fjump_tables, options::OPT_fno_jump_tables,
- true))
- CmdArgs.push_back("-fno-jump-tables");
-
- if (Args.hasFlag(options::OPT_fprofile_sample_accurate,
- options::OPT_fno_profile_sample_accurate, false))
- CmdArgs.push_back("-fprofile-sample-accurate");
-
- if (!Args.hasFlag(options::OPT_fpreserve_as_comments,
- options::OPT_fno_preserve_as_comments, true))
- CmdArgs.push_back("-fno-preserve-as-comments");
+ Args.addOptOutFlag(CmdArgs, options::OPT_fjump_tables,
+ options::OPT_fno_jump_tables);
+ Args.addOptInFlag(CmdArgs, options::OPT_fprofile_sample_accurate,
+ options::OPT_fno_profile_sample_accurate);
+ Args.addOptOutFlag(CmdArgs, options::OPT_fpreserve_as_comments,
+ options::OPT_fno_preserve_as_comments);
if (Arg *A = Args.getLastArg(options::OPT_mregparm_EQ)) {
CmdArgs.push_back("-mregparm");
@@ -4905,8 +5498,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false))
- CmdArgs.push_back("-fdefault-calling-conv=stdcall");
+ if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false)) {
+ if (Triple.getArch() == llvm::Triple::m68k)
+ CmdArgs.push_back("-fdefault-calling-conv=rtdcall");
+ else
+ CmdArgs.push_back("-fdefault-calling-conv=stdcall");
+ }
if (Args.hasArg(options::OPT_fenable_matrix)) {
// enable-matrix is needed by both the LangOpts and by LLVM.
@@ -4932,9 +5529,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
assert(FPKeepKindStr && "unknown FramePointerKind");
CmdArgs.push_back(FPKeepKindStr);
- if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss,
- options::OPT_fno_zero_initialized_in_bss, true))
- CmdArgs.push_back("-fno-zero-initialized-in-bss");
+ Args.addOptOutFlag(CmdArgs, options::OPT_fzero_initialized_in_bss,
+ options::OPT_fno_zero_initialized_in_bss);
bool OFastEnabled = isOptimizationLevelFast(Args);
// If -Ofast is the optimization level, then -fstrict-aliasing should be
@@ -4948,31 +5544,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_strict_aliasing, TBAAOnByDefault))
CmdArgs.push_back("-relaxed-aliasing");
if (!Args.hasFlag(options::OPT_fstruct_path_tbaa,
- options::OPT_fno_struct_path_tbaa))
+ options::OPT_fno_struct_path_tbaa, true))
CmdArgs.push_back("-no-struct-path-tbaa");
- if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums,
- false))
- CmdArgs.push_back("-fstrict-enums");
- if (!Args.hasFlag(options::OPT_fstrict_return, options::OPT_fno_strict_return,
- true))
- CmdArgs.push_back("-fno-strict-return");
- if (Args.hasFlag(options::OPT_fallow_editor_placeholders,
- options::OPT_fno_allow_editor_placeholders, false))
- CmdArgs.push_back("-fallow-editor-placeholders");
- if (Args.hasFlag(options::OPT_fstrict_vtable_pointers,
- options::OPT_fno_strict_vtable_pointers,
- false))
- CmdArgs.push_back("-fstrict-vtable-pointers");
- if (Args.hasFlag(options::OPT_fforce_emit_vtables,
- options::OPT_fno_force_emit_vtables,
- false))
- CmdArgs.push_back("-fforce-emit-vtables");
- if (!Args.hasFlag(options::OPT_foptimize_sibling_calls,
- options::OPT_fno_optimize_sibling_calls))
- CmdArgs.push_back("-mdisable-tail-calls");
- if (Args.hasFlag(options::OPT_fno_escaping_block_tail_calls,
- options::OPT_fescaping_block_tail_calls, false))
- CmdArgs.push_back("-fno-escaping-block-tail-calls");
+ Args.addOptInFlag(CmdArgs, options::OPT_fstrict_enums,
+ options::OPT_fno_strict_enums);
+ Args.addOptOutFlag(CmdArgs, options::OPT_fstrict_return,
+ options::OPT_fno_strict_return);
+ Args.addOptInFlag(CmdArgs, options::OPT_fallow_editor_placeholders,
+ options::OPT_fno_allow_editor_placeholders);
+ Args.addOptInFlag(CmdArgs, options::OPT_fstrict_vtable_pointers,
+ options::OPT_fno_strict_vtable_pointers);
+ Args.addOptInFlag(CmdArgs, options::OPT_fforce_emit_vtables,
+ options::OPT_fno_force_emit_vtables);
+ Args.addOptOutFlag(CmdArgs, options::OPT_foptimize_sibling_calls,
+ options::OPT_fno_optimize_sibling_calls);
+ Args.addOptOutFlag(CmdArgs, options::OPT_fescaping_block_tail_calls,
+ options::OPT_fno_escaping_block_tail_calls);
Args.AddLastArg(CmdArgs, options::OPT_ffine_grained_bitfield_accesses,
options::OPT_fno_fine_grained_bitfield_accesses);
@@ -4980,10 +5567,12 @@ 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);
+ Args.AddLastArg(CmdArgs, options::OPT_fexperimental_omit_vtable_rtti,
+ options::OPT_fno_experimental_omit_vtable_rtti);
+
// Handle segmented stacks.
- if (Args.hasFlag(options::OPT_fsplit_stack, options::OPT_fno_split_stack,
- false))
- CmdArgs.push_back("-fsplit-stack");
+ Args.addOptInFlag(CmdArgs, options::OPT_fsplit_stack,
+ options::OPT_fno_split_stack);
// -fprotect-parens=0 is default.
if (Args.hasFlag(options::OPT_fprotect_parens,
@@ -5063,9 +5652,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 https://openradar.appspot.com/7198997), 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
@@ -5078,14 +5667,28 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-mms-bitfields");
}
+ if (Triple.isWindowsGNUEnvironment()) {
+ Args.addOptOutFlag(CmdArgs, options::OPT_fauto_import,
+ options::OPT_fno_auto_import);
+ }
+
+ if (Args.hasFlag(options::OPT_fms_volatile, options::OPT_fno_ms_volatile,
+ Triple.isX86() && D.IsCLMode()))
+ CmdArgs.push_back("-fms-volatile");
+
// Non-PIC code defaults to -fdirect-access-external-data while PIC code
// defaults to -fno-direct-access-external-data. Pass the option if different
// from the default.
if (Arg *A = Args.getLastArg(options::OPT_fdirect_access_external_data,
- options::OPT_fno_direct_access_external_data))
+ options::OPT_fno_direct_access_external_data)) {
if (A->getOption().matches(options::OPT_fdirect_access_external_data) !=
(PICLevel == 0))
A->render(Args, CmdArgs);
+ } else if (PICLevel == 0 && Triple.isLoongArch()) {
+ // Some targets default to -fno-direct-access-external-data even for
+ // -fno-pic.
+ CmdArgs.push_back("-fno-direct-access-external-data");
+ }
if (Args.hasFlag(options::OPT_fno_plt, options::OPT_fplt, false)) {
CmdArgs.push_back("-fno-plt");
@@ -5100,19 +5703,30 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Freestanding)
CmdArgs.push_back("-ffreestanding");
+ Args.AddLastArg(CmdArgs, options::OPT_fno_knr_functions);
+
// This is a coarse approximation of what llvm-gcc actually does, both
// -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more
// complicated ways.
+ auto SanitizeArgs = TC.getSanitizerArgs(Args);
+
+ bool IsAsyncUnwindTablesDefault =
+ TC.getDefaultUnwindTableLevel(Args) == ToolChain::UnwindTableLevel::Asynchronous;
+ bool IsSyncUnwindTablesDefault =
+ TC.getDefaultUnwindTableLevel(Args) == ToolChain::UnwindTableLevel::Synchronous;
+
+ bool AsyncUnwindTables = Args.hasFlag(
+ options::OPT_fasynchronous_unwind_tables,
+ options::OPT_fno_asynchronous_unwind_tables,
+ (IsAsyncUnwindTablesDefault || SanitizeArgs.needsUnwindTables()) &&
+ !Freestanding);
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");
+ Args.hasFlag(options::OPT_funwind_tables, options::OPT_fno_unwind_tables,
+ IsSyncUnwindTablesDefault && !Freestanding);
+ 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.
@@ -5121,7 +5735,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));
@@ -5132,20 +5746,78 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
TC.addClangTargetOptions(Args, CmdArgs, JA.getOffloadingDeviceKind());
- // FIXME: Handle -mtune=.
- (void)Args.hasArg(options::OPT_mtune_EQ);
-
if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
StringRef CM = A->getValue();
- if (CM == "small" || CM == "kernel" || CM == "medium" || CM == "large" ||
- CM == "tiny") {
- if (Triple.isOSAIX() && CM == "medium")
- CmdArgs.push_back("-mcmodel=large");
- else
- A->render(Args, CmdArgs);
+ bool Ok = false;
+ if (Triple.isOSAIX() && CM == "medium")
+ CM = "large";
+ if (Triple.isAArch64(64)) {
+ Ok = CM == "tiny" || CM == "small" || CM == "large";
+ if (CM == "large" && RelocationModel != llvm::Reloc::Static)
+ D.Diag(diag::err_drv_argument_only_allowed_with)
+ << A->getAsString(Args) << "-fno-pic";
+ } else if (Triple.isLoongArch()) {
+ if (CM == "extreme" &&
+ Args.hasFlagNoClaim(options::OPT_fplt, options::OPT_fno_plt, false))
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << A->getAsString(Args) << "-fplt";
+ Ok = CM == "normal" || CM == "medium" || CM == "extreme";
+ // Convert to LLVM recognizable names.
+ if (Ok)
+ CM = llvm::StringSwitch<StringRef>(CM)
+ .Case("normal", "small")
+ .Case("extreme", "large")
+ .Default(CM);
+ } else if (Triple.isPPC64() || Triple.isOSAIX()) {
+ Ok = CM == "small" || CM == "medium" || CM == "large";
+ } else if (Triple.isRISCV()) {
+ if (CM == "medlow")
+ CM = "small";
+ else if (CM == "medany")
+ CM = "medium";
+ Ok = CM == "small" || CM == "medium";
+ } else if (Triple.getArch() == llvm::Triple::x86_64) {
+ Ok = llvm::is_contained({"small", "kernel", "medium", "large", "tiny"},
+ CM);
+ } else if (Triple.isNVPTX() || Triple.isAMDGPU()) {
+ // NVPTX/AMDGPU does not care about the code model and will accept
+ // whatever works for the host.
+ Ok = true;
+ } else if (Triple.isSPARC64()) {
+ if (CM == "medlow")
+ CM = "small";
+ else if (CM == "medmid")
+ CM = "medium";
+ else if (CM == "medany")
+ CM = "large";
+ Ok = CM == "small" || CM == "medium" || CM == "large";
+ }
+ if (Ok) {
+ CmdArgs.push_back(Args.MakeArgString("-mcmodel=" + CM));
} else {
- D.Diag(diag::err_drv_invalid_argument_to_option)
- << CM << A->getOption().getName();
+ D.Diag(diag::err_drv_unsupported_option_argument_for_target)
+ << A->getSpelling() << CM << TripleStr;
+ }
+ }
+
+ if (Triple.getArch() == llvm::Triple::x86_64) {
+ bool IsMediumCM = false;
+ bool IsLargeCM = false;
+ if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
+ IsMediumCM = StringRef(A->getValue()) == "medium";
+ IsLargeCM = StringRef(A->getValue()) == "large";
+ }
+ if (Arg *A = Args.getLastArg(options::OPT_mlarge_data_threshold_EQ)) {
+ if (!IsMediumCM && !IsLargeCM) {
+ D.Diag(diag::warn_drv_large_data_threshold_invalid_code_model)
+ << A->getOption().getRenderName();
+ } else {
+ A->render(Args, CmdArgs);
+ }
+ } else if (IsMediumCM) {
+ CmdArgs.push_back("-mlarge-data-threshold=65536");
+ } else if (IsLargeCM) {
+ CmdArgs.push_back("-mlarge-data-threshold=0");
}
}
@@ -5162,8 +5834,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_mtls_size_EQ);
}
+ if (isTLSDESCEnabled(TC, Args))
+ CmdArgs.push_back("-enable-tlsdesc");
+
// 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));
@@ -5171,40 +5846,23 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
RenderTargetOptions(Triple, Args, KernelOrKext, CmdArgs);
- // FIXME: For now we want to demote any errors to warnings, when they have
- // been raised for asking the wrong question of scalable vectors, such as
- // asking for the fixed number of elements. This may happen because code that
- // is not yet ported to work for scalable vectors uses the wrong interfaces,
- // whereas the behaviour is actually correct. Emitting a warning helps bring
- // up scalable vector support in an incremental way. When scalable vector
- // support is stable enough, all uses of wrong interfaces should be considered
- // as errors, but until then, we can live with a warning being emitted by the
- // compiler. This way, Clang can be used to compile code with scalable vectors
- // and identify possible issues.
- if (isa<BackendJobAction>(JA)) {
- CmdArgs.push_back("-mllvm");
- CmdArgs.push_back("-treat-scalable-fixed-error-as-warning");
- }
-
- // These two are potentially updated by AddClangCLArgs.
- codegenoptions::DebugInfoKind DebugInfoKind = codegenoptions::NoDebugInfo;
- bool EmitCodeView = false;
-
// Add clang-cl arguments.
types::ID InputType = Input.getType();
if (D.IsCLMode())
- AddClangCLArgs(Args, InputType, CmdArgs, &DebugInfoKind, &EmitCodeView);
+ AddClangCLArgs(Args, InputType, CmdArgs);
+ llvm::codegenoptions::DebugInfoKind DebugInfoKind =
+ llvm::codegenoptions::NoDebugInfo;
DwarfFissionKind DwarfFission = DwarfFissionKind::None;
- renderDebugOptions(TC, D, RawTriple, Args, EmitCodeView,
- types::isLLVMIR(InputType), CmdArgs, DebugInfoKind,
- DwarfFission);
+ renderDebugOptions(TC, D, RawTriple, Args, types::isLLVMIR(InputType),
+ CmdArgs, Output, DebugInfoKind, DwarfFission);
// Add the split debug info name to the command lines here so we
// can propagate it to the backend.
bool SplitDWARF = (DwarfFission != DwarfFissionKind::None) &&
(TC.getTriple().isOSBinFormatELF() ||
- TC.getTriple().isOSBinFormatWasm()) &&
+ TC.getTriple().isOSBinFormatWasm() ||
+ TC.getTriple().isOSBinFormatCOFF()) &&
(isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA) ||
isa<BackendJobAction>(JA));
if (SplitDWARF) {
@@ -5252,12 +5910,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
Args.AddAllArgs(CmdArgs, options::OPT_fshow_skipped_includes);
- if (D.CCPrintHeaders && !D.CCGenDiagnostics) {
+ if (D.CCPrintHeadersFormat && !D.CCGenDiagnostics) {
CmdArgs.push_back("-header-include-file");
CmdArgs.push_back(!D.CCPrintHeadersFilename.empty()
? D.CCPrintHeadersFilename.c_str()
: "-");
CmdArgs.push_back("-sys-header-deps");
+ CmdArgs.push_back(Args.MakeArgString(
+ "-header-include-format=" +
+ std::string(headerIncludeFormatKindToString(D.CCPrintHeadersFormat))));
+ CmdArgs.push_back(
+ Args.MakeArgString("-header-include-filtering=" +
+ std::string(headerIncludeFilteringKindToString(
+ D.CCPrintHeadersFiltering))));
}
Args.AddLastArg(CmdArgs, options::OPT_P);
Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout);
@@ -5293,7 +5958,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
StringRef Val = A->getValue();
if (Triple.isX86() && Triple.isOSBinFormatELF()) {
if (Val != "all" && Val != "labels" && Val != "none" &&
- !Val.startswith("list="))
+ !Val.starts_with("list="))
D.Diag(diag::err_drv_invalid_value)
<< A->getAsString(Args) << A->getValue();
else
@@ -5315,27 +5980,24 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fdata-sections");
}
- if (!Args.hasFlag(options::OPT_funique_section_names,
- options::OPT_fno_unique_section_names, true))
- CmdArgs.push_back("-fno-unique-section-names");
-
- if (Args.hasFlag(options::OPT_funique_internal_linkage_names,
- options::OPT_fno_unique_internal_linkage_names, false))
- CmdArgs.push_back("-funique-internal-linkage-names");
-
- if (Args.hasFlag(options::OPT_funique_basic_block_section_names,
- options::OPT_fno_unique_basic_block_section_names, false))
- CmdArgs.push_back("-funique-basic-block-section-names");
+ Args.addOptOutFlag(CmdArgs, options::OPT_funique_section_names,
+ options::OPT_fno_unique_section_names);
+ Args.addOptInFlag(CmdArgs, options::OPT_funique_internal_linkage_names,
+ options::OPT_fno_unique_internal_linkage_names);
+ Args.addOptInFlag(CmdArgs, options::OPT_funique_basic_block_section_names,
+ options::OPT_fno_unique_basic_block_section_names);
+ Args.addOptInFlag(CmdArgs, options::OPT_fconvergent_functions,
+ options::OPT_fno_convergent_functions);
if (Arg *A = Args.getLastArg(options::OPT_fsplit_machine_functions,
options::OPT_fno_split_machine_functions)) {
- // This codegen pass is only available on x86-elf targets.
- if (Triple.isX86() && Triple.isOSBinFormatELF()) {
- if (A->getOption().matches(options::OPT_fsplit_machine_functions))
+ if (!A->getOption().matches(options::OPT_fno_split_machine_functions)) {
+ // This codegen pass is only available on x86 and AArch64 ELF targets.
+ if ((Triple.isX86() || Triple.isAArch64()) && Triple.isOSBinFormatELF())
A->render(Args, CmdArgs);
- } else {
- D.Diag(diag::err_drv_unsupported_opt_for_target)
- << A->getAsString(Args) << TripleStr;
+ else
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getAsString(Args) << TripleStr;
}
}
@@ -5347,15 +6009,21 @@ 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, JA, Output, Args, SanitizeArgs, CmdArgs);
Args.AddLastArg(CmdArgs, options::OPT_fclang_abi_compat_EQ);
- // Add runtime flag for PS4 when PGO, coverage, or sanitizers are enabled.
- if (RawTriple.isPS4CPU() &&
+ if (getLastProfileSampleUseArg(Args) &&
+ Args.hasArg(options::OPT_fsample_profile_use_profi)) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-sample-profile-use-profi");
+ }
+
+ // Add runtime flag for PS4/PS5 when PGO, coverage, or sanitizers are enabled.
+ if (RawTriple.isPS() &&
!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
- PS4cpu::addProfileRTArgs(TC, Args, CmdArgs);
- PS4cpu::addSanitizerArgs(TC, CmdArgs);
+ PScpu::addProfileRTArgs(TC, Args, CmdArgs);
+ PScpu::addSanitizerArgs(TC, Args, CmdArgs);
}
// Pass options for controlling the default header search paths.
@@ -5417,16 +6085,35 @@ 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);
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_Wsystem_headers_in_module_EQ);
+
if (Args.hasFlag(options::OPT_pedantic, options::OPT_no_pedantic, false))
CmdArgs.push_back("-pedantic");
Args.AddLastArg(CmdArgs, options::OPT_pedantic_errors);
Args.AddLastArg(CmdArgs, options::OPT_w);
- // Fixed point flags
- if (Args.hasFlag(options::OPT_ffixed_point, options::OPT_fno_fixed_point,
- /*Default=*/false))
- Args.AddLastArg(CmdArgs, options::OPT_ffixed_point);
+ Args.addOptInFlag(CmdArgs, options::OPT_ffixed_point,
+ options::OPT_fno_fixed_point);
if (Arg *A = Args.getLastArg(options::OPT_fcxx_abi_EQ))
A->render(Args, CmdArgs);
@@ -5434,6 +6121,12 @@ 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);
+ Args.AddLastArg(CmdArgs, options::OPT_fexperimental_omit_vtable_rtti,
+ options::OPT_fno_experimental_omit_vtable_rtti);
+
+ 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).
//
@@ -5476,11 +6169,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_ftrigraphs,
options::OPT_fno_trigraphs);
-
- // HIP headers has minimum C++ standard requirements. Therefore set the
- // default language standard.
- if (IsHIP)
- CmdArgs.push_back(IsWindowsMSVC ? "-std=c++14" : "-std=c++11");
}
// GCC's behavior for -Wwrite-strings is a bit strange:
@@ -5523,31 +6211,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (!ShouldEnableAutolink(Args, TC, JA))
CmdArgs.push_back("-fno-autolink");
- // Add in -fdebug-compilation-dir if necessary.
- addDebugCompDirArg(Args, CmdArgs, D.getVFS());
+ Args.AddLastArg(CmdArgs, options::OPT_ftemplate_depth_EQ);
+ Args.AddLastArg(CmdArgs, options::OPT_foperator_arrow_depth_EQ);
+ Args.AddLastArg(CmdArgs, options::OPT_fconstexpr_depth_EQ);
+ Args.AddLastArg(CmdArgs, options::OPT_fconstexpr_steps_EQ);
- addDebugPrefixMapArg(D, Args, CmdArgs);
-
- if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_,
- options::OPT_ftemplate_depth_EQ)) {
- CmdArgs.push_back("-ftemplate-depth");
- CmdArgs.push_back(A->getValue());
- }
-
- if (Arg *A = Args.getLastArg(options::OPT_foperator_arrow_depth_EQ)) {
- CmdArgs.push_back("-foperator-arrow-depth");
- CmdArgs.push_back(A->getValue());
- }
-
- if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_depth_EQ)) {
- CmdArgs.push_back("-fconstexpr-depth");
- CmdArgs.push_back(A->getValue());
- }
-
- if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_steps_EQ)) {
- CmdArgs.push_back("-fconstexpr-steps");
- CmdArgs.push_back(A->getValue());
- }
+ Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
if (Args.hasArg(options::OPT_fexperimental_new_constant_interpreter))
CmdArgs.push_back("-fexperimental-new-constant-interpreter");
@@ -5574,7 +6243,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
"standalone", "objc", "swift", "swift-5.0", "swift-4.2", "swift-4.1",
};
- if (find(kCFABIs, StringRef(A->getValue())) == std::end(kCFABIs))
+ if (!llvm::is_contained(kCFABIs, StringRef(A->getValue())))
D.Diag(diag::err_drv_invalid_cf_runtime_abi) << A->getValue();
else
A->render(Args, CmdArgs);
@@ -5590,9 +6259,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue());
}
- if (Args.hasFlag(options::OPT_fstack_size_section,
- options::OPT_fno_stack_size_section, RawTriple.isPS4()))
- CmdArgs.push_back("-fstack-size-section");
+ Args.addOptInFlag(CmdArgs, options::OPT_fstack_size_section,
+ options::OPT_fno_stack_size_section);
if (Args.hasArg(options::OPT_fstack_usage)) {
CmdArgs.push_back("-stack-usage-file");
@@ -5612,25 +6280,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
else
CmdArgs.push_back("19");
- if (Arg *A = Args.getLastArg(options::OPT_fmacro_backtrace_limit_EQ)) {
- CmdArgs.push_back("-fmacro-backtrace-limit");
- CmdArgs.push_back(A->getValue());
- }
-
- if (Arg *A = Args.getLastArg(options::OPT_ftemplate_backtrace_limit_EQ)) {
- CmdArgs.push_back("-ftemplate-backtrace-limit");
- CmdArgs.push_back(A->getValue());
- }
-
- if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_backtrace_limit_EQ)) {
- CmdArgs.push_back("-fconstexpr-backtrace-limit");
- CmdArgs.push_back(A->getValue());
- }
-
- if (Arg *A = Args.getLastArg(options::OPT_fspell_checking_limit_EQ)) {
- CmdArgs.push_back("-fspell-checking-limit");
- CmdArgs.push_back(A->getValue());
- }
+ Args.AddLastArg(CmdArgs, options::OPT_fconstexpr_backtrace_limit_EQ);
+ Args.AddLastArg(CmdArgs, options::OPT_fmacro_backtrace_limit_EQ);
+ Args.AddLastArg(CmdArgs, options::OPT_ftemplate_backtrace_limit_EQ);
+ Args.AddLastArg(CmdArgs, options::OPT_fspell_checking_limit_EQ);
+ Args.AddLastArg(CmdArgs, options::OPT_fcaret_diagnostics_max_lines_EQ);
// Pass -fmessage-length=.
unsigned MessageLength = 0;
@@ -5648,22 +6302,33 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(
Args.MakeArgString("-fmessage-length=" + Twine(MessageLength)));
+ if (Arg *A = Args.getLastArg(options::OPT_frandomize_layout_seed_EQ))
+ CmdArgs.push_back(
+ Args.MakeArgString("-frandomize-layout-seed=" + Twine(A->getValue(0))));
+
+ if (Arg *A = Args.getLastArg(options::OPT_frandomize_layout_seed_file_EQ))
+ CmdArgs.push_back(Args.MakeArgString("-frandomize-layout-seed-file=" +
+ Twine(A->getValue(0))));
+
// -fvisibility= and -fvisibility-ms-compat are of a piece.
if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ,
options::OPT_fvisibility_ms_compat)) {
if (A->getOption().matches(options::OPT_fvisibility_EQ)) {
- CmdArgs.push_back("-fvisibility");
- CmdArgs.push_back(A->getValue());
+ A->render(Args, CmdArgs);
} else {
assert(A->getOption().matches(options::OPT_fvisibility_ms_compat));
- CmdArgs.push_back("-fvisibility");
- CmdArgs.push_back("hidden");
- CmdArgs.push_back("-ftype-visibility");
- CmdArgs.push_back("default");
+ CmdArgs.push_back("-fvisibility=hidden");
+ CmdArgs.push_back("-ftype-visibility=default");
}
+ } else if (IsOpenMPDevice) {
+ // When compiling for the OpenMP device we want protected visibility by
+ // default. This prevents the device from accidentally preempting code on
+ // the host, makes the system more robust, and improves performance.
+ CmdArgs.push_back("-fvisibility=protected");
}
- if (!RawTriple.isPS4())
+ // PS4/PS5 process these options in addClangTargetOptions.
+ if (!RawTriple.isPS()) {
if (const Arg *A =
Args.getLastArg(options::OPT_fvisibility_from_dllstorageclass,
options::OPT_fno_visibility_from_dllstorageclass)) {
@@ -5677,26 +6342,42 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fvisibility_externs_nodllstorageclass_EQ);
}
}
-
- if (const Arg *A = Args.getLastArg(options::OPT_mignore_xcoff_visibility)) {
- if (Triple.isOSAIX())
- CmdArgs.push_back("-mignore-xcoff-visibility");
- else
- D.Diag(diag::err_drv_unsupported_opt_for_target)
- << A->getAsString(Args) << TripleStr;
}
-
if (Args.hasFlag(options::OPT_fvisibility_inlines_hidden,
options::OPT_fno_visibility_inlines_hidden, false))
CmdArgs.push_back("-fvisibility-inlines-hidden");
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);
+
+ // -fvisibility-global-new-delete-hidden is a deprecated spelling of
+ // -fvisibility-global-new-delete=force-hidden.
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_fvisibility_global_new_delete_hidden)) {
+ D.Diag(diag::warn_drv_deprecated_arg)
+ << A->getAsString(Args)
+ << "-fvisibility-global-new-delete=force-hidden";
+ }
+
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_fvisibility_global_new_delete_EQ,
+ options::OPT_fvisibility_global_new_delete_hidden)) {
+ if (A->getOption().matches(options::OPT_fvisibility_global_new_delete_EQ)) {
+ A->render(Args, CmdArgs);
+ } else {
+ assert(A->getOption().matches(
+ options::OPT_fvisibility_global_new_delete_hidden));
+ CmdArgs.push_back("-fvisibility-global-new-delete=force-hidden");
+ }
+ }
Args.AddLastArg(CmdArgs, options::OPT_ftlsmodel_EQ);
+ if (Args.hasFlag(options::OPT_fnew_infallible,
+ options::OPT_fno_new_infallible, false))
+ CmdArgs.push_back("-fnew-infallible");
+
if (Args.hasFlag(options::OPT_fno_operator_names,
options::OPT_foperator_names, false))
CmdArgs.push_back("-fno-operator-names");
@@ -5705,8 +6386,23 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
Args.AddLastArg(CmdArgs, options::OPT_fdigraphs, options::OPT_fno_digraphs);
- Args.AddLastArg(CmdArgs, options::OPT_femulated_tls,
- options::OPT_fno_emulated_tls);
+ Args.AddLastArg(CmdArgs, options::OPT_fzero_call_used_regs_EQ);
+
+ if (Args.hasFlag(options::OPT_femulated_tls, options::OPT_fno_emulated_tls,
+ Triple.hasDefaultEmulatedTLS()))
+ CmdArgs.push_back("-femulated-tls");
+
+ Args.addOptInFlag(CmdArgs, options::OPT_fcheck_new,
+ options::OPT_fno_check_new);
+
+ if (Arg *A = Args.getLastArg(options::OPT_fzero_call_used_regs_EQ)) {
+ // FIXME: There's no reason for this to be restricted to X86. The backend
+ // code needs to be changed to include the appropriate function calls
+ // automatically.
+ if (!Triple.isX86() && !Triple.isAArch64())
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getAsString(Args) << TripleStr;
+ }
// AltiVec-like language extensions aren't relevant for assembling.
if (!isa<PreprocessJobAction>(JA) || Output.getType() != types::TY_PP_Asm)
@@ -5737,6 +6433,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,
@@ -5752,12 +6451,30 @@ 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 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,
+ // 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, 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-cuda-force-full-runtime");
+ CmdArgs.push_back("-fopenmp-assume-threads-oversubscription");
+ if (Args.hasArg(options::OPT_fopenmp_assume_no_thread_state))
+ CmdArgs.push_back("-fopenmp-assume-no-thread-state");
+ if (Args.hasArg(options::OPT_fopenmp_assume_no_nested_parallelism))
+ CmdArgs.push_back("-fopenmp-assume-no-nested-parallelism");
+ if (Args.hasArg(options::OPT_fopenmp_offload_mandatory))
+ CmdArgs.push_back("-fopenmp-offload-mandatory");
+ if (Args.hasArg(options::OPT_fopenmp_force_usm))
+ CmdArgs.push_back("-fopenmp-force-usm");
break;
default:
// By default, if Clang doesn't know how to generate useful OpenMP code
@@ -5772,10 +6489,16 @@ 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);
+ Args.addOptOutFlag(CmdArgs, options::OPT_fopenmp_extensions,
+ options::OPT_fno_openmp_extensions);
}
- const SanitizerArgs &Sanitize = TC.getSanitizerArgs();
- Sanitize.addArgs(TC, Args, CmdArgs, InputType);
+ // Forward the new driver to change offloading code generation.
+ if (Args.hasFlag(options::OPT_offload_new_driver,
+ options::OPT_no_offload_new_driver, false))
+ CmdArgs.push_back("--offload-new-driver");
+
+ SanitizeArgs.addArgs(TC, Args, CmdArgs, InputType);
const XRayArgs &XRay = TC.getXRayArgs();
XRay.addArgs(TC, Args, CmdArgs, InputType);
@@ -5791,7 +6514,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Arg *A = Args.getLastArg(options::OPT_fpatchable_function_entry_EQ)) {
StringRef S0 = A->getValue(), S = S0;
unsigned Size, Offset = 0;
- if (!Triple.isAArch64() && !Triple.isRISCV() && !Triple.isX86())
+ if (!Triple.isAArch64() && !Triple.isLoongArch() && !Triple.isRISCV() &&
+ !Triple.isX86())
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getAsString(Args) << TripleStr;
else if (S.consumeInteger(10, Size) ||
@@ -5808,6 +6532,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ Args.AddLastArg(CmdArgs, options::OPT_fms_hotpatch);
+
if (TC.SupportsProfiling()) {
Args.AddLastArg(CmdArgs, options::OPT_pg);
@@ -5835,6 +6561,35 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ if (Arg *A = Args.getLastArgNoClaim(options::OPT_pg)) {
+ if (TC.getTriple().isOSzOS()) {
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getAsString(Args) << TripleStr;
+ }
+ }
+ if (Arg *A = Args.getLastArgNoClaim(options::OPT_p)) {
+ if (!(TC.getTriple().isOSAIX() || TC.getTriple().isOSOpenBSD())) {
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getAsString(Args) << TripleStr;
+ }
+ }
+ if (Arg *A = Args.getLastArgNoClaim(options::OPT_p, options::OPT_pg)) {
+ if (A->getOption().matches(options::OPT_p)) {
+ A->claim();
+ if (TC.getTriple().isOSAIX() && !Args.hasArgNoClaim(options::OPT_pg))
+ CmdArgs.push_back("-pg");
+ }
+ }
+
+ // Reject AIX-specific link options on other targets.
+ if (!TC.getTriple().isOSAIX()) {
+ for (const Arg *A : Args.filtered(options::OPT_b, options::OPT_K,
+ options::OPT_mxcoff_build_id_EQ)) {
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getSpelling() << TripleStr;
+ }
+ }
+
if (Args.getLastArg(options::OPT_fapple_kext) ||
(Args.hasArg(options::OPT_mkernel) && types::isCXX(InputType)))
CmdArgs.push_back("-fapple-kext");
@@ -5846,12 +6601,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_parseable_fixits);
Args.AddLastArg(CmdArgs, options::OPT_ftime_report);
Args.AddLastArg(CmdArgs, options::OPT_ftime_report_EQ);
- Args.AddLastArg(CmdArgs, options::OPT_ftime_trace);
- Args.AddLastArg(CmdArgs, options::OPT_ftime_trace_granularity_EQ);
Args.AddLastArg(CmdArgs, options::OPT_ftrapv);
Args.AddLastArg(CmdArgs, options::OPT_malign_double);
Args.AddLastArg(CmdArgs, options::OPT_fno_temp_file);
+ if (const char *Name = C.getTimeTraceFile(&JA)) {
+ CmdArgs.push_back(Args.MakeArgString("-ftime-trace=" + Twine(Name)));
+ Args.AddLastArg(CmdArgs, options::OPT_ftime_trace_granularity_EQ);
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_ftrapv_handler_EQ)) {
CmdArgs.push_back("-ftrapv-handler");
CmdArgs.push_back(A->getValue());
@@ -5882,20 +6640,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_funroll_loops,
options::OPT_fno_unroll_loops);
+ Args.AddLastArg(CmdArgs, options::OPT_fstrict_flex_arrays_EQ);
+
Args.AddLastArg(CmdArgs, options::OPT_pthread);
- if (Args.hasFlag(options::OPT_mspeculative_load_hardening,
- options::OPT_mno_speculative_load_hardening, false))
- CmdArgs.push_back(Args.MakeArgString("-mspeculative-load-hardening"));
+ Args.addOptInFlag(CmdArgs, options::OPT_mspeculative_load_hardening,
+ options::OPT_mno_speculative_load_hardening);
RenderSSPOptions(D, TC, Args, CmdArgs, KernelOrKext);
RenderSCPOptions(TC, Args, CmdArgs);
RenderTrivialAutoVarInitOptions(D, TC, Args, CmdArgs);
- // Translate -mstackrealign
- if (Args.hasFlag(options::OPT_mstackrealign, options::OPT_mno_stackrealign,
- false))
- CmdArgs.push_back(Args.MakeArgString("-mstackrealign"));
+ Args.AddLastArg(CmdArgs, options::OPT_fswift_async_fp_EQ);
+
+ Args.addOptInFlag(CmdArgs, options::OPT_mstackrealign,
+ options::OPT_mno_stackrealign);
if (Args.hasArg(options::OPT_mstack_alignment)) {
StringRef alignment = Args.getLastArgValue(options::OPT_mstack_alignment);
@@ -5911,9 +6670,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-mstack-probe-size=0");
}
- if (!Args.hasFlag(options::OPT_mstack_arg_probe,
- options::OPT_mno_stack_arg_probe, true))
- CmdArgs.push_back(Args.MakeArgString("-mno-stack-arg-probe"));
+ Args.addOptOutFlag(CmdArgs, options::OPT_mstack_arg_probe,
+ options::OPT_mno_stack_arg_probe);
if (Arg *A = Args.getLastArg(options::OPT_mrestrict_it,
options::OPT_mno_restrict_it)) {
@@ -5922,34 +6680,36 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-arm-restrict-it");
} else {
CmdArgs.push_back("-mllvm");
- CmdArgs.push_back("-arm-no-restrict-it");
+ CmdArgs.push_back("-arm-default-it");
}
- } else if (Triple.isOSWindows() &&
- (Triple.getArch() == llvm::Triple::arm ||
- Triple.getArch() == llvm::Triple::thumb)) {
- // Windows on ARM expects restricted IT blocks
- CmdArgs.push_back("-mllvm");
- CmdArgs.push_back("-arm-restrict-it");
}
// Forward -cl options to -cc1
RenderOpenCLOptions(Args, CmdArgs, InputType);
+ // Forward hlsl options to -cc1
+ RenderHLSLOptions(Args, CmdArgs, InputType);
+
+ // Forward OpenACC options to -cc1
+ RenderOpenACCOptions(D, Args, CmdArgs, InputType);
+
if (IsHIP) {
if (Args.hasFlag(options::OPT_fhip_new_launch_api,
options::OPT_fno_hip_new_launch_api, true))
CmdArgs.push_back("-fhip-new-launch-api");
- if (Args.hasFlag(options::OPT_fgpu_allow_device_init,
- options::OPT_fno_gpu_allow_device_init, false))
- CmdArgs.push_back("-fgpu-allow-device-init");
+ Args.addOptInFlag(CmdArgs, options::OPT_fgpu_allow_device_init,
+ options::OPT_fno_gpu_allow_device_init);
+ Args.AddLastArg(CmdArgs, options::OPT_hipstdpar);
+ Args.AddLastArg(CmdArgs, options::OPT_hipstdpar_interpose_alloc);
+ Args.addOptInFlag(CmdArgs, options::OPT_fhip_kernel_arg_name,
+ options::OPT_fno_hip_kernel_arg_name);
}
if (IsCuda || IsHIP) {
- if (Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false))
+ if (IsRDCMode)
CmdArgs.push_back("-fgpu-rdc");
- if (Args.hasFlag(options::OPT_fgpu_defer_diag,
- options::OPT_fno_gpu_defer_diag, false))
- CmdArgs.push_back("-fgpu-defer-diag");
+ Args.addOptInFlag(CmdArgs, options::OPT_fgpu_defer_diag,
+ options::OPT_fno_gpu_defer_diag);
if (Args.hasFlag(options::OPT_fgpu_exclude_wrong_side_overloads,
options::OPT_fno_gpu_exclude_wrong_side_overloads,
false)) {
@@ -5958,11 +6718,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ // Forward -nogpulib to -cc1.
+ if (Args.hasArg(options::OPT_nogpulib))
+ CmdArgs.push_back("-nogpulib");
+
if (Arg *A = Args.getLastArg(options::OPT_fcf_protection_EQ)) {
CmdArgs.push_back(
Args.MakeArgString(Twine("-fcf-protection=") + A->getValue()));
}
+ if (Arg *A = Args.getLastArg(options::OPT_mfunction_return_EQ))
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-mfunction-return=") + A->getValue()));
+
+ Args.AddLastArg(CmdArgs, options::OPT_mindirect_branch_cs_prefix);
+
// Forward -f options with positive and negative forms; we translate these by
// hand. Do not propagate PGO options to the GPU-side compilations as the
// profile info is for the host-side compilation only.
@@ -5997,9 +6767,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
RenderBuiltinOptions(TC, RawTriple, Args, CmdArgs);
- if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
- options::OPT_fno_assume_sane_operator_new))
- CmdArgs.push_back("-fno-assume-sane-operator-new");
+ Args.addOptOutFlag(CmdArgs, options::OPT_fassume_sane_operator_new,
+ options::OPT_fno_assume_sane_operator_new);
+
+ if (Args.hasFlag(options::OPT_fapinotes, options::OPT_fno_apinotes, false))
+ CmdArgs.push_back("-fapinotes");
+ if (Args.hasFlag(options::OPT_fapinotes_modules,
+ options::OPT_fno_apinotes_modules, false))
+ CmdArgs.push_back("-fapinotes-modules");
+ Args.AddLastArg(CmdArgs, options::OPT_fapinotes_swift_version);
// -fblocks=0 is default.
if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks,
@@ -6017,24 +6793,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (TC.IsEncodeExtendedBlockSignatureDefault())
CmdArgs.push_back("-fencode-extended-block-signature");
- if (Args.hasFlag(options::OPT_fcoroutines_ts, options::OPT_fno_coroutines_ts,
- false) &&
- types::isCXX(InputType)) {
- CmdArgs.push_back("-fcoroutines-ts");
- }
+ if (Args.hasFlag(options::OPT_fcoro_aligned_allocation,
+ options::OPT_fno_coro_aligned_allocation, false) &&
+ types::isCXX(InputType))
+ CmdArgs.push_back("-fcoro-aligned-allocation");
Args.AddLastArg(CmdArgs, options::OPT_fdouble_square_bracket_attributes,
options::OPT_fno_double_square_bracket_attributes);
- // -faccess-control is default.
- if (Args.hasFlag(options::OPT_fno_access_control,
- options::OPT_faccess_control, false))
- CmdArgs.push_back("-fno-access-control");
-
- // -felide-constructors is the default.
- if (Args.hasFlag(options::OPT_fno_elide_constructors,
- options::OPT_felide_constructors, false))
- CmdArgs.push_back("-fno-elide-constructors");
+ Args.addOptOutFlag(CmdArgs, options::OPT_faccess_control,
+ options::OPT_fno_access_control);
+ Args.addOptOutFlag(CmdArgs, options::OPT_felide_constructors,
+ options::OPT_fno_elide_constructors);
ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
@@ -6053,7 +6823,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasFlag(
options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit,
!RawTriple.isOSAIX() && !RawTriple.isOSWindows() &&
- TC.getArch() != llvm::Triple::xcore &&
((RawTriple.getVendor() != llvm::Triple::MipsTechnologies) ||
RawTriple.hasEnvironment())) ||
KernelOrKext)
@@ -6064,10 +6833,28 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
RawTriple.isOSDarwin() && !KernelOrKext))
CmdArgs.push_back("-fregister-global-dtors-with-atexit");
- // -fno-use-line-directives is default.
- if (Args.hasFlag(options::OPT_fuse_line_directives,
- options::OPT_fno_use_line_directives, false))
- CmdArgs.push_back("-fuse-line-directives");
+ Args.addOptInFlag(CmdArgs, options::OPT_fuse_line_directives,
+ options::OPT_fno_use_line_directives);
+
+ // -fno-minimize-whitespace is default.
+ if (Args.hasFlag(options::OPT_fminimize_whitespace,
+ options::OPT_fno_minimize_whitespace, false)) {
+ types::ID InputType = Inputs[0].getType();
+ if (!isDerivedFromC(InputType))
+ D.Diag(diag::err_drv_opt_unsupported_input_type)
+ << "-fminimize-whitespace" << types::getTypeName(InputType);
+ CmdArgs.push_back("-fminimize-whitespace");
+ }
+
+ // -fno-keep-system-includes is default.
+ if (Args.hasFlag(options::OPT_fkeep_system_includes,
+ options::OPT_fno_keep_system_includes, false)) {
+ types::ID InputType = Inputs[0].getType();
+ if (!isDerivedFromC(InputType))
+ D.Diag(diag::err_drv_opt_unsupported_input_type)
+ << "-fkeep-system-includes" << types::getTypeName(InputType);
+ CmdArgs.push_back("-fkeep-system-includes");
+ }
// -fms-extensions=0 is default.
if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
@@ -6082,6 +6869,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (IsMSVCCompat)
CmdArgs.push_back("-fms-compatibility");
+ if (Triple.isWindowsMSVCEnvironment() && !D.IsCLMode() &&
+ Args.hasArg(options::OPT_fms_runtime_lib_EQ))
+ ProcessVSRuntimeLibrary(Args, CmdArgs);
+
// Handle -fgcc-version, if present.
VersionTuple GNUCVer;
if (Arg *A = Args.getLastArg(options::OPT_fgnuc_version_EQ)) {
@@ -6090,8 +6881,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
StringRef Val = A->getValue();
Val = Val.empty() ? "0" : Val; // Treat "" as 0 or disable.
bool Invalid = GNUCVer.tryParse(Val);
- unsigned Minor = GNUCVer.getMinor().getValueOr(0);
- unsigned Patch = GNUCVer.getSubminor().getValueOr(0);
+ unsigned Minor = GNUCVer.getMinor().value_or(0);
+ unsigned Patch = GNUCVer.getSubminor().value_or(0);
if (Invalid || GNUCVer.getBuild() || Minor >= 100 || Patch >= 100) {
D.Diag(diag::err_drv_invalid_value)
<< A->getAsString(Args) << A->getValue();
@@ -6133,7 +6924,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
.Case("c++14", "-std=c++14")
.Case("c++17", "-std=c++17")
.Case("c++20", "-std=c++20")
- .Case("c++latest", "-std=c++2b")
+ // TODO add c++23 and c++26 when MSVC supports it.
+ .Case("c++latest", "-std=c++26")
.Default("");
if (LanguageStandard.empty())
D.Diag(clang::diag::warn_drv_unused_argument)
@@ -6150,14 +6942,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(LanguageStandard.data());
}
- // -fno-borland-extensions is default.
- if (Args.hasFlag(options::OPT_fborland_extensions,
- options::OPT_fno_borland_extensions, false))
- CmdArgs.push_back("-fborland-extensions");
+ Args.addOptInFlag(CmdArgs, options::OPT_fborland_extensions,
+ options::OPT_fno_borland_extensions);
- // -fno-declspec is default, except for PS4.
+ // -fno-declspec is default, except for PS4/PS5.
if (Args.hasFlag(options::OPT_fdeclspec, options::OPT_fno_declspec,
- RawTriple.isPS4()))
+ RawTriple.isPS()))
CmdArgs.push_back("-fdeclspec");
else if (Args.hasArg(options::OPT_fno_declspec))
CmdArgs.push_back("-fno-declspec"); // Explicitly disabling __declspec.
@@ -6166,39 +6956,62 @@ 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.
- // Many old Windows SDK versions require this to parse.
- // FIXME: MSVC introduced /Zc:twoPhase- to disable this behavior in their
- // compiler. We should be able to disable this by default at some point.
- if (Args.hasFlag(options::OPT_fdelayed_template_parsing,
- options::OPT_fno_delayed_template_parsing, IsWindowsMSVC))
- CmdArgs.push_back("-fdelayed-template-parsing");
-
// -fgnu-keywords default varies depending on language; only pass if
// specified.
Args.AddLastArg(CmdArgs, options::OPT_fgnu_keywords,
options::OPT_fno_gnu_keywords);
- if (Args.hasFlag(options::OPT_fgnu89_inline, options::OPT_fno_gnu89_inline,
- false))
- CmdArgs.push_back("-fgnu89-inline");
+ Args.addOptInFlag(CmdArgs, options::OPT_fgnu89_inline,
+ options::OPT_fno_gnu89_inline);
- if (Args.hasArg(options::OPT_fno_inline))
- CmdArgs.push_back("-fno-inline");
+ const Arg *InlineArg = Args.getLastArg(options::OPT_finline_functions,
+ options::OPT_finline_hint_functions,
+ options::OPT_fno_inline_functions);
+ if (Arg *A = Args.getLastArg(options::OPT_finline, options::OPT_fno_inline)) {
+ if (A->getOption().matches(options::OPT_fno_inline))
+ A->render(Args, CmdArgs);
+ } else if (InlineArg) {
+ InlineArg->render(Args, CmdArgs);
+ }
+
+ Args.AddLastArg(CmdArgs, options::OPT_finline_max_stacksize_EQ);
+
+ // FIXME: Find a better way to determine whether we are in C++20.
+ bool HaveCxx20 =
+ Std &&
+ (Std->containsValue("c++2a") || Std->containsValue("gnu++2a") ||
+ Std->containsValue("c++20") || Std->containsValue("gnu++20") ||
+ Std->containsValue("c++2b") || Std->containsValue("gnu++2b") ||
+ Std->containsValue("c++23") || Std->containsValue("gnu++23") ||
+ Std->containsValue("c++2c") || Std->containsValue("gnu++2c") ||
+ Std->containsValue("c++26") || Std->containsValue("gnu++26") ||
+ Std->containsValue("c++latest") || Std->containsValue("gnu++latest"));
+ bool HaveModules =
+ RenderModulesOptions(C, D, Args, Input, Output, HaveCxx20, CmdArgs);
- Args.AddLastArg(CmdArgs, options::OPT_finline_functions,
- options::OPT_finline_hint_functions,
- options::OPT_fno_inline_functions);
+ // -fdelayed-template-parsing is default when targeting MSVC.
+ // Many old Windows SDK versions require this to parse.
+ //
+ // According to
+ // https://learn.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance?view=msvc-170,
+ // MSVC actually defaults to -fno-delayed-template-parsing (/Zc:twoPhase-
+ // with MSVC CLI) if using C++20. So we match the behavior with MSVC here to
+ // not enable -fdelayed-template-parsing by default after C++20.
+ //
+ // FIXME: Given -fdelayed-template-parsing is a source of bugs, we should be
+ // able to disable this by default at some point.
+ if (Args.hasFlag(options::OPT_fdelayed_template_parsing,
+ options::OPT_fno_delayed_template_parsing,
+ IsWindowsMSVC && !HaveCxx20)) {
+ if (HaveCxx20)
+ D.Diag(clang::diag::warn_drv_delayed_template_parsing_after_cxx20);
- // FIXME: Find a better way to determine whether the language has modules
- // support by default, or just assume that all languages do.
- bool HaveModules =
- Std && (Std->containsValue("c++2a") || Std->containsValue("c++20") ||
- Std->containsValue("c++latest"));
- RenderModulesOptions(C, D, Args, Input, Output, CmdArgs, HaveModules);
+ CmdArgs.push_back("-fdelayed-template-parsing");
+ }
if (Args.hasFlag(options::OPT_fpch_validate_input_files_content,
options::OPT_fno_pch_validate_input_files_content, false))
@@ -6213,9 +7026,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
false))
CmdArgs.push_back("-fmodules-debuginfo");
- Args.AddLastArg(CmdArgs, options::OPT_flegacy_pass_manager,
- options::OPT_fno_legacy_pass_manager);
-
ObjCRuntime Runtime = AddObjCRuntimeArgs(Args, Inputs, CmdArgs, rewriteKind);
RenderObjCOptions(TC, D, RawTriple, Args, Runtime, rewriteKind != RK_None,
Input, CmdArgs);
@@ -6266,22 +7076,23 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
// C++ "sane" operator new.
- if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
- options::OPT_fno_assume_sane_operator_new))
- CmdArgs.push_back("-fno-assume-sane-operator-new");
+ Args.addOptOutFlag(CmdArgs, options::OPT_fassume_sane_operator_new,
+ options::OPT_fno_assume_sane_operator_new);
+
+ // -fassume-unique-vtables is on by default.
+ Args.addOptOutFlag(CmdArgs, options::OPT_fassume_unique_vtables,
+ options::OPT_fno_assume_unique_vtables);
// -frelaxed-template-template-args is off by default, as it is a severe
// breaking change until a corresponding change to template partial ordering
// is provided.
- if (Args.hasFlag(options::OPT_frelaxed_template_template_args,
- options::OPT_fno_relaxed_template_template_args, false))
- CmdArgs.push_back("-frelaxed-template-template-args");
+ Args.addOptInFlag(CmdArgs, options::OPT_frelaxed_template_template_args,
+ options::OPT_fno_relaxed_template_template_args);
// -fsized-deallocation is off by default, as it is an ABI-breaking change for
// most platforms.
- if (Args.hasFlag(options::OPT_fsized_deallocation,
- options::OPT_fno_sized_deallocation, false))
- CmdArgs.push_back("-fsized-deallocation");
+ Args.addOptInFlag(CmdArgs, options::OPT_fsized_deallocation,
+ options::OPT_fno_sized_deallocation);
// -faligned-allocation is on by default in C++17 onwards and otherwise off
// by default.
@@ -6304,15 +7115,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fconstant-cfstrings is default, and may be subject to argument translation
// on Darwin.
if (!Args.hasFlag(options::OPT_fconstant_cfstrings,
- options::OPT_fno_constant_cfstrings) ||
+ options::OPT_fno_constant_cfstrings, true) ||
!Args.hasFlag(options::OPT_mconstant_cfstrings,
- options::OPT_mno_constant_cfstrings))
+ options::OPT_mno_constant_cfstrings, true))
CmdArgs.push_back("-fno-constant-cfstrings");
- // -fno-pascal-strings is default, only pass non-default.
- if (Args.hasFlag(options::OPT_fpascal_strings,
- options::OPT_fno_pascal_strings, false))
- CmdArgs.push_back("-fpascal-strings");
+ Args.addOptInFlag(CmdArgs, options::OPT_fpascal_strings,
+ options::OPT_fno_pascal_strings);
// Honor -fpack-struct= and -fpack-struct, if given. Note that
// -fno-pack-struct doesn't apply to -fpack-struct=.
@@ -6344,18 +7153,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-Qn");
// -fno-common is the default, set -fcommon only when that flag is set.
- if (Args.hasFlag(options::OPT_fcommon, options::OPT_fno_common, false))
- CmdArgs.push_back("-fcommon");
+ Args.addOptInFlag(CmdArgs, options::OPT_fcommon, options::OPT_fno_common);
// -fsigned-bitfields is default, and clang doesn't yet support
// -funsigned-bitfields.
if (!Args.hasFlag(options::OPT_fsigned_bitfields,
- options::OPT_funsigned_bitfields))
+ options::OPT_funsigned_bitfields, true))
D.Diag(diag::warn_drv_clang_unsupported)
<< Args.getLastArg(options::OPT_funsigned_bitfields)->getAsString(Args);
// -fsigned-bitfields is default, and clang doesn't support -fno-for-scope.
- if (!Args.hasFlag(options::OPT_ffor_scope, options::OPT_fno_for_scope))
+ if (!Args.hasFlag(options::OPT_ffor_scope, options::OPT_fno_for_scope, true))
D.Diag(diag::err_drv_clang_unsupported)
<< Args.getLastArg(options::OPT_fno_for_scope)->getAsString(Args);
@@ -6377,15 +7185,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
RenderDiagnosticsOptions(D, Args, CmdArgs);
- // -fno-asm-blocks is default.
- if (Args.hasFlag(options::OPT_fasm_blocks, options::OPT_fno_asm_blocks,
- false))
- CmdArgs.push_back("-fasm-blocks");
+ Args.addOptInFlag(CmdArgs, options::OPT_fasm_blocks,
+ options::OPT_fno_asm_blocks);
- // -fgnu-inline-asm is default.
- if (!Args.hasFlag(options::OPT_fgnu_inline_asm,
- options::OPT_fno_gnu_inline_asm, true))
- CmdArgs.push_back("-fno-gnu-inline-asm");
+ Args.addOptOutFlag(CmdArgs, options::OPT_fgnu_inline_asm,
+ options::OPT_fno_gnu_inline_asm);
// Enable vectorization per default according to the optimization level
// selected. For optimization levels that want vectorization we use the alias
@@ -6421,21 +7225,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fno-dollars-in-identifiers");
}
- // -funit-at-a-time is default, and we don't support -fno-unit-at-a-time for
- // practical purposes.
- if (Arg *A = Args.getLastArg(options::OPT_funit_at_a_time,
- options::OPT_fno_unit_at_a_time)) {
- if (A->getOption().matches(options::OPT_fno_unit_at_a_time))
- D.Diag(diag::warn_drv_clang_unsupported) << A->getAsString(Args);
- }
-
- if (Args.hasFlag(options::OPT_fapple_pragma_pack,
- options::OPT_fno_apple_pragma_pack, false))
- CmdArgs.push_back("-fapple-pragma-pack");
-
- if (Args.hasFlag(options::OPT_fxl_pragma_pack,
- options::OPT_fno_xl_pragma_pack, RawTriple.isOSAIX()))
- CmdArgs.push_back("-fxl-pragma-pack");
+ Args.addOptInFlag(CmdArgs, options::OPT_fapple_pragma_pack,
+ options::OPT_fno_apple_pragma_pack);
// Remarks can be enabled with any of the `-f.*optimization-record.*` flags.
if (willEmitRemarks(Args) && checkRemarksOptions(D, Args, Triple))
@@ -6446,6 +7237,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (RewriteImports)
CmdArgs.push_back("-frewrite-imports");
+ Args.addOptInFlag(CmdArgs, options::OPT_fdirectives_only,
+ options::OPT_fno_directives_only);
+
// Enable rewrite includes if the user's asked for it or if we're generating
// diagnostics.
// TODO: Once -module-dependency-dir works with -frewrite-includes it'd be
@@ -6466,6 +7260,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_dM);
Args.AddLastArg(CmdArgs, options::OPT_dD);
+ Args.AddLastArg(CmdArgs, options::OPT_dI);
Args.AddLastArg(CmdArgs, options::OPT_fmax_tokens_EQ);
@@ -6490,6 +7285,35 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
A->claim();
}
+ // Turn -fplugin-arg-pluginname-key=value into
+ // -plugin-arg-pluginname key=value
+ // GCC has an actual plugin_argument struct with key/value pairs that it
+ // passes to its plugins, but we don't, so just pass it on as-is.
+ //
+ // The syntax for -fplugin-arg- is ambiguous if both plugin name and
+ // argument key are allowed to contain dashes. GCC therefore only
+ // allows dashes in the key. We do the same.
+ for (const Arg *A : Args.filtered(options::OPT_fplugin_arg)) {
+ auto ArgValue = StringRef(A->getValue());
+ auto FirstDashIndex = ArgValue.find('-');
+ StringRef PluginName = ArgValue.substr(0, FirstDashIndex);
+ StringRef Arg = ArgValue.substr(FirstDashIndex + 1);
+
+ A->claim();
+ if (FirstDashIndex == StringRef::npos || Arg.empty()) {
+ if (PluginName.empty()) {
+ D.Diag(diag::warn_drv_missing_plugin_name) << A->getAsString(Args);
+ } else {
+ D.Diag(diag::warn_drv_missing_plugin_arg)
+ << PluginName << A->getAsString(Args);
+ }
+ continue;
+ }
+
+ CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-arg-") + PluginName));
+ CmdArgs.push_back(Args.MakeArgString(Arg));
+ }
+
// Forward -fpass-plugin=name.so to -cc1.
for (const Arg *A : Args.filtered(options::OPT_fpass_plugin_EQ)) {
CmdArgs.push_back(
@@ -6497,25 +7321,36 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
A->claim();
}
+ // Forward --vfsoverlay to -cc1.
+ for (const Arg *A : Args.filtered(options::OPT_vfsoverlay)) {
+ CmdArgs.push_back("--vfsoverlay");
+ CmdArgs.push_back(A->getValue());
+ A->claim();
+ }
+
+ Args.addOptInFlag(CmdArgs, options::OPT_fsafe_buffer_usage_suggestions,
+ options::OPT_fno_safe_buffer_usage_suggestions);
+
// Setup statistics file output.
SmallString<128> StatsFile = getStatsFileName(Args, Output, Input, D);
- if (!StatsFile.empty())
+ if (!StatsFile.empty()) {
CmdArgs.push_back(Args.MakeArgString(Twine("-stats-file=") + StatsFile));
+ if (D.CCPrintInternalStats)
+ CmdArgs.push_back("-stats-file-append");
+ }
// Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option
// parser.
- // -finclude-default-header flag is for preprocessor,
- // do not pass it to other cc1 commands when save-temps is enabled
- if (C.getDriver().isSaveTempsEnabled() &&
- !isa<PreprocessJobAction>(JA)) {
- for (auto Arg : Args.filtered(options::OPT_Xclang)) {
- Arg->claim();
- if (StringRef(Arg->getValue()) != "-finclude-default-header")
- CmdArgs.push_back(Arg->getValue());
+ for (auto Arg : Args.filtered(options::OPT_Xclang)) {
+ Arg->claim();
+ // -finclude-default-header flag is for preprocessor,
+ // do not pass it to other cc1 commands when save-temps is enabled
+ if (C.getDriver().isSaveTempsEnabled() &&
+ !isa<PreprocessJobAction>(JA)) {
+ if (StringRef(Arg->getValue()) == "-finclude-default-header")
+ continue;
}
- }
- else {
- Args.AddAllArgValues(CmdArgs, options::OPT_Xclang);
+ CmdArgs.push_back(Arg->getValue());
}
for (const Arg *A : Args.filtered(options::OPT_mllvm)) {
A->claim();
@@ -6559,7 +7394,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
auto FRecordSwitches =
Args.hasFlag(options::OPT_frecord_command_line,
options::OPT_fno_record_command_line, false);
- if (FRecordSwitches && !Triple.isOSBinFormatELF())
+ if (FRecordSwitches && !Triple.isOSBinFormatELF() &&
+ !Triple.isOSBinFormatXCOFF() && !Triple.isOSBinFormatMachO())
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< Args.getLastArg(options::OPT_frecord_command_line)->getAsString(Args)
<< TripleStr;
@@ -6587,13 +7423,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- // Host-side cuda compilation receives all device-side outputs in a single
- // fatbin as Inputs[1]. Include the binary with -fcuda-include-gpubinary.
+ // Host-side offloading compilation receives all device-side outputs. Include
+ // them in the host compilation depending on the target. If the host inputs
+ // are not empty we use the new-driver scheme, otherwise use the old scheme.
if ((IsCuda || IsHIP) && CudaDeviceInput) {
+ CmdArgs.push_back("-fcuda-include-gpubinary");
+ CmdArgs.push_back(CudaDeviceInput->getFilename());
+ } else if (!HostOffloadingInputs.empty()) {
+ if ((IsCuda || IsHIP) && !IsRDCMode) {
+ assert(HostOffloadingInputs.size() == 1 && "Only one input expected");
CmdArgs.push_back("-fcuda-include-gpubinary");
- CmdArgs.push_back(CudaDeviceInput->getFilename());
- if (Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false))
- CmdArgs.push_back("-fgpu-rdc");
+ CmdArgs.push_back(HostOffloadingInputs.front().getFilename());
+ } else {
+ for (const InputInfo Input : HostOffloadingInputs)
+ CmdArgs.push_back(Args.MakeArgString("-fembed-offload-object=" +
+ TC.getInputFilename(Input)));
+ }
}
if (IsCuda) {
@@ -6612,10 +7457,30 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
auto CUID = cast<InputAction>(SourceAction)->getId();
if (!CUID.empty())
CmdArgs.push_back(Args.MakeArgString(Twine("-cuid=") + Twine(CUID)));
+
+ // -ffast-math turns on -fgpu-approx-transcendentals implicitly, but will
+ // be overriden by -fno-gpu-approx-transcendentals.
+ bool UseApproxTranscendentals = Args.hasFlag(
+ options::OPT_ffast_math, options::OPT_fno_fast_math, false);
+ if (Args.hasFlag(options::OPT_fgpu_approx_transcendentals,
+ options::OPT_fno_gpu_approx_transcendentals,
+ UseApproxTranscendentals))
+ CmdArgs.push_back("-fgpu-approx-transcendentals");
+ } else {
+ Args.claimAllArgs(options::OPT_fgpu_approx_transcendentals,
+ options::OPT_fno_gpu_approx_transcendentals);
}
- if (IsHIP)
+ if (IsHIP) {
CmdArgs.push_back("-fcuda-allow-variadic-functions");
+ Args.AddLastArg(CmdArgs, options::OPT_fgpu_default_stream_EQ);
+ }
+
+ Args.AddLastArg(CmdArgs, options::OPT_foffload_uniform_block,
+ options::OPT_fno_offload_uniform_block);
+
+ Args.AddLastArg(CmdArgs, options::OPT_foffload_implicit_host_device_templates,
+ options::OPT_fno_offload_implicit_host_device_templates);
if (IsCudaDevice || IsHIPDevice) {
StringRef InlineThresh =
@@ -6627,13 +7492,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ if (IsHIPDevice)
+ Args.addOptOutFlag(CmdArgs,
+ options::OPT_fhip_fp32_correctly_rounded_divide_sqrt,
+ options::OPT_fno_hip_fp32_correctly_rounded_divide_sqrt);
+
// OpenMP offloading device jobs take the argument -fopenmp-host-ir-file-path
// to specify the result of the compile phase on the host, so the meaningful
- // device declarations can be identified. Also, -fopenmp-is-device is passed
- // along to tell the frontend that it is generating code for a device, so that
- // only the relevant declarations are emitted.
+ // device declarations can be identified. Also, -fopenmp-is-target-device is
+ // passed along to tell the frontend that it is generating code for a device,
+ // so that only the relevant declarations are emitted.
if (IsOpenMPDevice) {
- CmdArgs.push_back("-fopenmp-is-device");
+ CmdArgs.push_back("-fopenmp-is-target-device");
if (OpenMPDeviceInput) {
CmdArgs.push_back("-fopenmp-host-ir-file-path");
CmdArgs.push_back(Args.MakeArgString(OpenMPDeviceInput->getFilename()));
@@ -6643,28 +7513,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Triple.isAMDGPU()) {
handleAMDGPUCodeObjectVersionOptions(D, Args, CmdArgs);
- if (Args.hasFlag(options::OPT_munsafe_fp_atomics,
- options::OPT_mno_unsafe_fp_atomics, /*Default=*/false))
- CmdArgs.push_back("-munsafe-fp-atomics");
+ Args.addOptInFlag(CmdArgs, options::OPT_munsafe_fp_atomics,
+ options::OPT_mno_unsafe_fp_atomics);
+ Args.addOptOutFlag(CmdArgs, options::OPT_mamdgpu_ieee,
+ options::OPT_mno_amdgpu_ieee);
}
// For all the host OpenMP offloading compile jobs we need to pass the targets
// information using -fopenmp-targets= option.
if (JA.isHostOffloading(Action::OFK_OpenMP)) {
- SmallString<128> TargetInfo("-fopenmp-targets=");
+ SmallString<128> Targets("-fopenmp-targets=");
- Arg *Tgts = Args.getLastArg(options::OPT_fopenmp_targets_EQ);
- assert(Tgts && Tgts->getNumValues() &&
- "OpenMP offloading has to have targets specified.");
- for (unsigned i = 0; i < Tgts->getNumValues(); ++i) {
- if (i)
- TargetInfo += ',';
- // We need to get the string from the triple because it may be not exactly
- // the same as the one we get directly from the arguments.
- llvm::Triple T(Tgts->getValue(i));
- TargetInfo += T.getTriple();
- }
- CmdArgs.push_back(Args.MakeArgString(TargetInfo.str()));
+ SmallVector<std::string, 4> Triples;
+ auto TCRange = C.getOffloadToolChains<Action::OFK_OpenMP>();
+ std::transform(TCRange.first, TCRange.second, std::back_inserter(Triples),
+ [](auto TC) { return TC.second->getTripleString(); });
+ CmdArgs.push_back(Args.MakeArgString(Targets + llvm::join(Triples, ",")));
}
bool VirtualFunctionElimination =
@@ -6692,31 +7556,55 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
if (WholeProgramVTables) {
- // Propagate -fwhole-program-vtables if this is an LTO compile.
- if (IsUsingLTO)
- CmdArgs.push_back("-fwhole-program-vtables");
+ // PS4 uses the legacy LTO API, which does not support this feature in
+ // ThinLTO mode.
+ bool IsPS4 = getToolChain().getTriple().isPS4();
+
// Check if we passed LTO options but they were suppressed because this is a
// device offloading action, or we passed device offload LTO options which
// were suppressed because this is not the device offload action.
+ // Check if we are using PS4 in regular LTO mode.
// Otherwise, issue an error.
- else if (!D.isUsingLTO(!IsDeviceOffloadAction))
+ if ((!IsUsingLTO && !D.isUsingLTO(!IsDeviceOffloadAction)) ||
+ (IsPS4 && !UnifiedLTO && (D.getLTOMode() != LTOK_Full)))
D.Diag(diag::err_drv_argument_only_allowed_with)
<< "-fwhole-program-vtables"
- << "-flto";
+ << ((IsPS4 && !UnifiedLTO) ? "-flto=full" : "-flto");
+
+ // Propagate -fwhole-program-vtables if this is an LTO compile.
+ if (IsUsingLTO)
+ CmdArgs.push_back("-fwhole-program-vtables");
}
bool DefaultsSplitLTOUnit =
- (WholeProgramVTables || Sanitize.needsLTO()) &&
- (LTOMode == LTOK_Full || TC.canSplitThinLTOUnit());
+ ((WholeProgramVTables || SanitizeArgs.needsLTO()) &&
+ (LTOMode == LTOK_Full || TC.canSplitThinLTOUnit())) ||
+ (!Triple.isPS4() && UnifiedLTO);
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)
CmdArgs.push_back("-fsplit-lto-unit");
+ if (Arg *A = Args.getLastArg(options::OPT_ffat_lto_objects,
+ options::OPT_fno_fat_lto_objects)) {
+ if (IsUsingLTO && A->getOption().matches(options::OPT_ffat_lto_objects)) {
+ assert(LTOMode == LTOK_Full || LTOMode == LTOK_Thin);
+ if (!Triple.isOSBinFormatELF()) {
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getAsString(Args) << TC.getTripleString();
+ }
+ CmdArgs.push_back(Args.MakeArgString(
+ Twine("-flto=") + (LTOMode == LTOK_Thin ? "thin" : "full")));
+ CmdArgs.push_back("-flto-unit");
+ CmdArgs.push_back("-ffat-lto-objects");
+ A->render(Args, CmdArgs);
+ }
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_fglobal_isel,
options::OPT_fno_global_isel)) {
CmdArgs.push_back("-mllvm");
@@ -6765,34 +7653,31 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fforce-enable-int128");
}
- if (Args.hasFlag(options::OPT_fkeep_static_consts,
- options::OPT_fno_keep_static_consts, false))
- CmdArgs.push_back("-fkeep-static-consts");
-
- if (Args.hasFlag(options::OPT_fcomplete_member_pointers,
- options::OPT_fno_complete_member_pointers, false))
- CmdArgs.push_back("-fcomplete-member-pointers");
-
- if (!Args.hasFlag(options::OPT_fcxx_static_destructors,
- options::OPT_fno_cxx_static_destructors, true))
- CmdArgs.push_back("-fno-c++-static-destructors");
+ Args.addOptInFlag(CmdArgs, options::OPT_fkeep_static_consts,
+ options::OPT_fno_keep_static_consts);
+ Args.addOptInFlag(CmdArgs, options::OPT_fkeep_persistent_storage_variables,
+ options::OPT_fno_keep_persistent_storage_variables);
+ Args.addOptInFlag(CmdArgs, options::OPT_fcomplete_member_pointers,
+ options::OPT_fno_complete_member_pointers);
+ Args.addOptOutFlag(CmdArgs, options::OPT_fcxx_static_destructors,
+ options::OPT_fno_cxx_static_destructors);
addMachineOutlinerArgs(D, Args, CmdArgs, Triple, /*IsLTO=*/false);
if (Arg *A = Args.getLastArg(options::OPT_moutline_atomics,
options::OPT_mno_outline_atomics)) {
- if (A->getOption().matches(options::OPT_moutline_atomics)) {
- // Option -moutline-atomics supported for AArch64 target only.
- if (!Triple.isAArch64()) {
- D.Diag(diag::warn_drv_moutline_atomics_unsupported_opt)
- << Triple.getArchName();
- } else {
+ // Option -moutline-atomics supported for AArch64 target only.
+ if (!Triple.isAArch64()) {
+ D.Diag(diag::warn_drv_moutline_atomics_unsupported_opt)
+ << Triple.getArchName() << A->getOption().getName();
+ } else {
+ if (A->getOption().matches(options::OPT_moutline_atomics)) {
CmdArgs.push_back("-target-feature");
CmdArgs.push_back("+outline-atomics");
+ } else {
+ CmdArgs.push_back("-target-feature");
+ CmdArgs.push_back("-outline-atomics");
}
- } else {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("-outline-atomics");
}
} else if (Triple.isAArch64() &&
getToolChain().IsAArch64OutlineAtomicsDefault(Args)) {
@@ -6800,6 +7685,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("+outline-atomics");
}
+ if (Triple.isAArch64() &&
+ (Args.hasArg(options::OPT_mno_fmv) ||
+ (Triple.isAndroid() && Triple.isAndroidVersionLT(23)) ||
+ getToolChain().GetRuntimeLibType(Args) != ToolChain::RLT_CompilerRT)) {
+ // Disable Function Multiversioning on AArch64 target.
+ CmdArgs.push_back("-target-feature");
+ CmdArgs.push_back("-fmv");
+ }
+
if (Args.hasFlag(options::OPT_faddrsig, options::OPT_fno_addrsig,
(TC.getTriple().isOSBinFormatELF() ||
TC.getTriple().isOSBinFormatCOFF()) &&
@@ -6810,7 +7704,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-faddrsig");
if ((Triple.isOSBinFormatELF() || Triple.isOSBinFormatMachO()) &&
- (EH || UnwindTables || DebugInfoKind != codegenoptions::NoDebugInfo))
+ (EH || UnwindTables || AsyncUnwindTables ||
+ DebugInfoKind != llvm::codegenoptions::NoDebugInfo))
CmdArgs.push_back("-D__GCC_HAVE_DWARF2_CFI_ASM=1");
if (Arg *A = Args.getLastArg(options::OPT_fsymbol_partition_EQ)) {
@@ -6843,8 +7738,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
addDashXForInput(Args, Input, CmdArgs);
ArrayRef<InputInfo> FrontendInputs = Input;
- if (IsHeaderModulePrecompile)
- FrontendInputs = ModuleHeaderInputs;
+ if (IsExtractAPI)
+ FrontendInputs = ExtractAPIInputs;
else if (Input.isNothing())
FrontendInputs = {};
@@ -6857,13 +7752,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (D.CC1Main && !D.CCGenDiagnostics) {
// Invoke the CC1 directly in this process
- C.addCommand(std::make_unique<CC1Command>(JA, *this,
- ResponseFileSupport::AtFileUTF8(),
- Exec, CmdArgs, Inputs, Output));
+ C.addCommand(std::make_unique<CC1Command>(
+ JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs,
+ Output, D.getPrependArg()));
} else {
- C.addCommand(std::make_unique<Command>(JA, *this,
- ResponseFileSupport::AtFileUTF8(),
- Exec, CmdArgs, Inputs, Output));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs,
+ Output, D.getPrependArg()));
}
// Make the compile command echo its inputs for /showFilenames.
@@ -6894,11 +7789,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.ClaimAllArgs(options::OPT_emit_llvm);
}
-Clang::Clang(const ToolChain &TC)
+Clang::Clang(const ToolChain &TC, bool HasIntegratedBackend)
// CAUTION! The first constructor argument ("clang") is not arbitrary,
// as it is for other tools. Some operations on a Tool actually test
// whether that tool is Clang based on the Tool's Name as a string.
- : Tool("clang", "clang frontend", TC) {}
+ : Tool("clang", "clang frontend", TC), HasBackend(HasIntegratedBackend) {}
Clang::~Clang() {}
@@ -7096,66 +7991,20 @@ static EHFlags parseClangCLEHFlags(const Driver &D, const ArgList &Args) {
EH.NoUnwindC = true;
}
+ if (Args.hasArg(options::OPT__SLASH_kernel)) {
+ EH.Synch = false;
+ EH.NoUnwindC = false;
+ EH.Asynch = false;
+ }
+
return EH;
}
void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
- ArgStringList &CmdArgs,
- codegenoptions::DebugInfoKind *DebugInfoKind,
- bool *EmitCodeView) const {
- unsigned RTOptionID = options::OPT__SLASH_MT;
+ ArgStringList &CmdArgs) const {
bool isNVPTX = getToolChain().getTriple().isNVPTX();
- if (Args.hasArg(options::OPT__SLASH_LDd))
- // The /LDd option implies /MTd. The dependent lib part can be overridden,
- // but defining _DEBUG is sticky.
- RTOptionID = options::OPT__SLASH_MTd;
-
- if (Arg *A = Args.getLastArg(options::OPT__SLASH_M_Group))
- RTOptionID = A->getOption().getID();
-
- StringRef FlagForCRT;
- switch (RTOptionID) {
- case options::OPT__SLASH_MD:
- if (Args.hasArg(options::OPT__SLASH_LDd))
- CmdArgs.push_back("-D_DEBUG");
- CmdArgs.push_back("-D_MT");
- CmdArgs.push_back("-D_DLL");
- FlagForCRT = "--dependent-lib=msvcrt";
- break;
- case options::OPT__SLASH_MDd:
- CmdArgs.push_back("-D_DEBUG");
- CmdArgs.push_back("-D_MT");
- CmdArgs.push_back("-D_DLL");
- FlagForCRT = "--dependent-lib=msvcrtd";
- break;
- case options::OPT__SLASH_MT:
- if (Args.hasArg(options::OPT__SLASH_LDd))
- CmdArgs.push_back("-D_DEBUG");
- CmdArgs.push_back("-D_MT");
- CmdArgs.push_back("-flto-visibility-public-std");
- FlagForCRT = "--dependent-lib=libcmt";
- break;
- case options::OPT__SLASH_MTd:
- CmdArgs.push_back("-D_DEBUG");
- CmdArgs.push_back("-D_MT");
- CmdArgs.push_back("-flto-visibility-public-std");
- FlagForCRT = "--dependent-lib=libcmtd";
- break;
- default:
- llvm_unreachable("Unexpected option ID.");
- }
-
- if (Args.hasArg(options::OPT__SLASH_Zl)) {
- CmdArgs.push_back("-D_VC_NODEFAULTLIB");
- } else {
- CmdArgs.push_back(FlagForCRT.data());
-
- // This provides POSIX compatibility (maps 'open' to '_open'), which most
- // users want. The /Za flag to cl.exe turns this off, but it's not
- // implemented in clang.
- CmdArgs.push_back("--dependent-lib=oldnames");
- }
+ ProcessVSRuntimeLibrary(Args, CmdArgs);
if (Arg *ShowIncludes =
Args.getLastArg(options::OPT__SLASH_showIncludes,
@@ -7178,24 +8027,15 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
CmdArgs.push_back(Args.MakeArgString(Twine(LangOptions::SSPStrong)));
}
- // Emit CodeView if -Z7 or -gline-tables-only are present.
- if (Arg *DebugInfoArg = Args.getLastArg(options::OPT__SLASH_Z7,
- options::OPT_gline_tables_only)) {
- *EmitCodeView = true;
- if (DebugInfoArg->getOption().matches(options::OPT__SLASH_Z7))
- *DebugInfoKind = codegenoptions::DebugInfoConstructor;
- else
- *DebugInfoKind = codegenoptions::DebugLineTablesOnly;
- } else {
- *EmitCodeView = false;
- }
-
const Driver &D = getToolChain().getDriver();
+
EHFlags EH = parseClangCLEHFlags(D, Args);
if (!isNVPTX && (EH.Synch || EH.Asynch)) {
if (types::isCXX(InputType))
CmdArgs.push_back("-fcxx-exceptions");
CmdArgs.push_back("-fexceptions");
+ if (EH.Asynch)
+ CmdArgs.push_back("-fasync-exceptions");
}
if (types::isCXX(InputType) && EH.Synch && EH.NoUnwindC)
CmdArgs.push_back("-fexternc-nounwind");
@@ -7206,24 +8046,38 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
CmdArgs.push_back("-P");
}
- unsigned VolatileOptionID;
- if (getToolChain().getTriple().isX86())
- VolatileOptionID = options::OPT__SLASH_volatile_ms;
- else
- VolatileOptionID = options::OPT__SLASH_volatile_iso;
-
- if (Arg *A = Args.getLastArg(options::OPT__SLASH_volatile_Group))
- VolatileOptionID = A->getOption().getID();
-
- if (VolatileOptionID == options::OPT__SLASH_volatile_ms)
- CmdArgs.push_back("-fms-volatile");
-
if (Args.hasFlag(options::OPT__SLASH_Zc_dllexportInlines_,
options::OPT__SLASH_Zc_dllexportInlines,
false)) {
CmdArgs.push_back("-fno-dllexport-inlines");
}
+ if (Args.hasFlag(options::OPT__SLASH_Zc_wchar_t_,
+ options::OPT__SLASH_Zc_wchar_t, false)) {
+ CmdArgs.push_back("-fno-wchar");
+ }
+
+ if (Args.hasArg(options::OPT__SLASH_kernel)) {
+ llvm::Triple::ArchType Arch = getToolChain().getArch();
+ std::vector<std::string> Values =
+ Args.getAllArgValues(options::OPT__SLASH_arch);
+ if (!Values.empty()) {
+ llvm::SmallSet<std::string, 4> SupportedArches;
+ if (Arch == llvm::Triple::x86)
+ SupportedArches.insert("IA32");
+
+ for (auto &V : Values)
+ if (!SupportedArches.contains(V))
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << std::string("/arch:").append(V) << "/kernel";
+ }
+
+ CmdArgs.push_back("-fno-rtti");
+ if (Args.hasFlag(options::OPT__SLASH_GR, options::OPT__SLASH_GR_, false))
+ D.Diag(diag::err_drv_argument_not_allowed_with) << "/GR"
+ << "/kernel";
+ }
+
Arg *MostGeneralArg = Args.getLastArg(options::OPT__SLASH_vmg);
Arg *BestCaseArg = Args.getLastArg(options::OPT__SLASH_vmb);
if (MostGeneralArg && BestCaseArg)
@@ -7250,6 +8104,9 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
CmdArgs.push_back("-fms-memptr-rep=virtual");
}
+ if (Args.hasArg(options::OPT_regcall4))
+ CmdArgs.push_back("-regcall4");
+
// Parse the default calling convention options.
if (Arg *CCArg =
Args.getLastArg(options::OPT__SLASH_Gd, options::OPT__SLASH_Gr,
@@ -7286,6 +8143,9 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
CmdArgs.push_back(DCCFlag);
}
+ if (Args.hasArg(options::OPT__SLASH_Gregcall4))
+ CmdArgs.push_back("-regcall4");
+
Args.AddLastArg(CmdArgs, options::OPT_vtordisp_mode_EQ);
if (!Args.hasArg(options::OPT_fdiagnostics_format_EQ)) {
@@ -7293,7 +8153,10 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
CmdArgs.push_back("msvc");
}
- if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) {
+ if (Args.hasArg(options::OPT__SLASH_kernel))
+ CmdArgs.push_back("-fms-kernel");
+
+ for (const Arg *A : Args.filtered(options::OPT__SLASH_guard)) {
StringRef GuardArgs = A->getValue();
// The only valid options are "cf", "cf,nochecks", "cf-", "ehcont" and
// "ehcont-".
@@ -7312,6 +8175,7 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
} else {
D.Diag(diag::err_drv_invalid_value) << A->getSpelling() << GuardArgs;
}
+ A->claim();
}
}
@@ -7368,11 +8232,19 @@ void ClangAs::AddX86TargetArgs(const ArgList &Args,
CmdArgs.push_back(Args.MakeArgString("-x86-asm-syntax=" + Value));
} else {
getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << Value;
+ << A->getSpelling() << Value;
}
}
}
+void ClangAs::AddLoongArchTargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ CmdArgs.push_back("-target-abi");
+ CmdArgs.push_back(loongarch::getLoongArchABI(getToolChain().getDriver(), Args,
+ getToolChain().getTriple())
+ .data());
+}
+
void ClangAs::AddRISCVTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
const llvm::Triple &Triple = getToolChain().getTriple();
@@ -7380,6 +8252,12 @@ void ClangAs::AddRISCVTargetArgs(const ArgList &Args,
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName.data());
+
+ if (Args.hasFlag(options::OPT_mdefault_build_attributes,
+ options::OPT_mno_default_build_attributes, true)) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-riscv-add-build-attributes");
+ }
}
void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
@@ -7411,6 +8289,8 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-triple");
CmdArgs.push_back(Args.MakeArgString(TripleStr));
+ getToolChain().addClangCC1ASTargetOptions(Args, CmdArgs);
+
// Set the output mode, we currently only expect to be used as a real
// assembler.
CmdArgs.push_back("-filetype");
@@ -7422,7 +8302,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));
@@ -7438,11 +8318,14 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_I_Group);
// Determine the original source input.
- const Action *SourceAction = &JA;
- while (SourceAction->getKind() != Action::InputClass) {
- assert(!SourceAction->getInputs().empty() && "unexpected root action!");
- SourceAction = SourceAction->getInputs()[0];
- }
+ auto FindSource = [](const Action *S) -> const Action * {
+ while (S->getKind() != Action::InputClass) {
+ assert(!S->getInputs().empty() && "unexpected root action!");
+ S = S->getInputs()[0];
+ }
+ return S;
+ };
+ const Action *SourceAction = FindSource(&JA);
// Forward -g and handle debug info related flags, assuming we are dealing
// with an actual assembly file.
@@ -7452,14 +8335,12 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
WantDebug = !A->getOption().matches(options::OPT_g0) &&
!A->getOption().matches(options::OPT_ggdb0);
- unsigned DwarfVersion = ParseDebugDefaultVersion(getToolChain(), Args);
- if (const Arg *GDwarfN = getDwarfNArg(Args))
- DwarfVersion = DwarfVersionNum(GDwarfN->getSpelling());
+ llvm::codegenoptions::DebugInfoKind DebugInfoKind =
+ llvm::codegenoptions::NoDebugInfo;
- if (DwarfVersion == 0)
- DwarfVersion = getToolChain().GetDefaultDwarfVersion();
-
- codegenoptions::DebugInfoKind DebugInfoKind = codegenoptions::NoDebugInfo;
+ // Add the -fdebug-compilation-dir flag if needed.
+ const char *DebugCompilationDir =
+ addDebugCompDirArg(Args, CmdArgs, C.getDriver().getVFS());
if (SourceAction->getType() == types::TY_Asm ||
SourceAction->getType() == types::TY_PP_Asm) {
@@ -7467,12 +8348,11 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
// the guard for source type, however there is a test which asserts
// that some assembler invocation receives no -debug-info-kind,
// and it's not clear whether that test is just overly restrictive.
- DebugInfoKind = (WantDebug ? codegenoptions::DebugInfoConstructor
- : codegenoptions::NoDebugInfo);
- // Add the -fdebug-compilation-dir flag if needed.
- addDebugCompDirArg(Args, CmdArgs, C.getDriver().getVFS());
+ DebugInfoKind = (WantDebug ? llvm::codegenoptions::DebugInfoConstructor
+ : llvm::codegenoptions::NoDebugInfo);
- addDebugPrefixMapArg(getToolChain().getDriver(), Args, CmdArgs);
+ addDebugPrefixMapArg(getToolChain().getDriver(), getToolChain(), Args,
+ CmdArgs);
// Set the AT_producer to the clang version when using the integrated
// assembler on assembly source files.
@@ -7482,12 +8362,12 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
// And pass along -I options
Args.AddAllArgs(CmdArgs, options::OPT_I);
}
+ const unsigned DwarfVersion = getDwarfVersion(getToolChain(), Args);
RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, DwarfVersion,
llvm::DebuggerKind::Default);
renderDwarfFormat(D, Triple, Args, CmdArgs, DwarfVersion);
RenderDebugInfoCompressionArgs(Args, CmdArgs, D, getToolChain());
-
// Handle -fPIC et al -- the relocation-model affects the assembler
// for some targets.
llvm::Reloc::Model RelocationModel;
@@ -7563,6 +8443,11 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
}
break;
+ case llvm::Triple::loongarch32:
+ case llvm::Triple::loongarch64:
+ AddLoongArchTargetArgs(Args, CmdArgs);
+ break;
+
case llvm::Triple::riscv32:
case llvm::Triple::riscv64:
AddRISCVTargetArgs(Args, CmdArgs);
@@ -7581,6 +8466,29 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_mllvm);
+ if (DebugInfoKind > llvm::codegenoptions::NoDebugInfo && Output.isFilename())
+ addDebugObjectName(Args, CmdArgs, DebugCompilationDir,
+ Output.getFilename());
+
+ // Fixup any previous commands that use -object-file-name because when we
+ // generated them, the final .obj name wasn't yet known.
+ for (Command &J : C.getJobs()) {
+ if (SourceAction != FindSource(&J.getSource()))
+ continue;
+ auto &JArgs = J.getArguments();
+ for (unsigned I = 0; I < JArgs.size(); ++I) {
+ if (StringRef(JArgs[I]).starts_with("-object-file-name=") &&
+ Output.isFilename()) {
+ ArgStringList NewArgs(JArgs.begin(), JArgs.begin() + I);
+ addDebugObjectName(Args, NewArgs, DebugCompilationDir,
+ Output.getFilename());
+ NewArgs.append(JArgs.begin() + I + 1, JArgs.end());
+ J.replaceArguments(NewArgs);
+ break;
+ }
+ }
+ }
+
assert(Output.isFilename() && "Unexpected lipo output.");
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
@@ -7594,7 +8502,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
}
if (Triple.isAMDGPU())
- handleAMDGPUCodeObjectVersionOptions(D, Args, CmdArgs);
+ handleAMDGPUCodeObjectVersionOptions(D, Args, CmdArgs, /*IsCC1As=*/true);
assert(Input.isFilename() && "Invalid input.");
CmdArgs.push_back(Input.getFilename());
@@ -7602,13 +8510,13 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec = getToolChain().getDriver().getClangProgramPath();
if (D.CC1Main && !D.CCGenDiagnostics) {
// Invoke cc1as directly in this process.
- C.addCommand(std::make_unique<CC1Command>(JA, *this,
- ResponseFileSupport::AtFileUTF8(),
- Exec, CmdArgs, Inputs, Output));
+ C.addCommand(std::make_unique<CC1Command>(
+ JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs,
+ Output, D.getPrependArg()));
} else {
- C.addCommand(std::make_unique<Command>(JA, *this,
- ResponseFileSupport::AtFileUTF8(),
- Exec, CmdArgs, Inputs, Output));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs,
+ Output, D.getPrependArg()));
}
}
@@ -7625,8 +8533,10 @@ void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA,
// The bundling command looks like this:
// clang-offload-bundler -type=bc
// -targets=host-triple,openmp-triple1,openmp-triple2
- // -outputs=input_file
- // -inputs=unbundle_file_host,unbundle_file_tgt1,unbundle_file_tgt2"
+ // -output=output_file
+ // -input=unbundle_file_host
+ // -input=unbundle_file_tgt1
+ // -input=unbundle_file_tgt2
ArgStringList CmdArgs;
@@ -7658,31 +8568,41 @@ 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) &&
+ !StringRef(CurDep->getOffloadingArch()).empty()) {
+ 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.starts_with_insensitive("-march=");
+ if (Arch) {
+ GPUArchName = ArchStr.substr(7);
+ Triples += "-";
+ break;
+ }
+ }
+ Triples += GPUArchName.str();
+ }
}
CmdArgs.push_back(TCArgs.MakeArgString(Triples));
// Get bundled file command.
CmdArgs.push_back(
- TCArgs.MakeArgString(Twine("-outputs=") + Output.getFilename()));
+ TCArgs.MakeArgString(Twine("-output=") + Output.getFilename()));
// Get unbundled files command.
- SmallString<128> UB;
- UB += "-inputs=";
for (unsigned I = 0; I < Inputs.size(); ++I) {
- if (I)
- UB += ',';
+ SmallString<128> UB;
+ UB += "-input=";
// Find ToolChain for this input.
const ToolChain *CurTC = &getToolChain();
@@ -7697,14 +8617,18 @@ void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA,
} else {
UB += CurTC->getInputFilename(Inputs[I]);
}
+ CmdArgs.push_back(TCArgs.MakeArgString(UB));
}
- CmdArgs.push_back(TCArgs.MakeArgString(UB));
-
+ if (TCArgs.hasFlag(options::OPT_offload_compress,
+ options::OPT_no_offload_compress, false))
+ CmdArgs.push_back("-compress");
+ if (TCArgs.hasArg(options::OPT_v))
+ CmdArgs.push_back("-verbose");
// All the inputs are encoded as commands.
C.addCommand(std::make_unique<Command>(
JA, *this, ResponseFileSupport::None(),
TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())),
- CmdArgs, None, Output));
+ CmdArgs, std::nullopt, Output));
}
void OffloadBundler::ConstructJobMultipleOutputs(
@@ -7717,8 +8641,10 @@ void OffloadBundler::ConstructJobMultipleOutputs(
// The unbundling command looks like this:
// clang-offload-bundler -type=bc
// -targets=host-triple,openmp-triple1,openmp-triple2
- // -inputs=input_file
- // -outputs=unbundle_file_host,unbundle_file_tgt1,unbundle_file_tgt2"
+ // -input=input_file
+ // -output=unbundle_file_host
+ // -output=unbundle_file_tgt1
+ // -output=unbundle_file_tgt2
// -unbundle
ArgStringList CmdArgs;
@@ -7740,68 +8666,112 @@ 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.starts_with_insensitive("-march=");
+ if (Arch) {
+ GPUArchName = ArchStr.substr(7);
+ Triples += "-";
+ break;
+ }
+ }
+ Triples += GPUArchName.str();
+ }
}
CmdArgs.push_back(TCArgs.MakeArgString(Triples));
// Get bundled file command.
CmdArgs.push_back(
- TCArgs.MakeArgString(Twine("-inputs=") + Input.getFilename()));
+ TCArgs.MakeArgString(Twine("-input=") + Input.getFilename()));
// Get unbundled files command.
- SmallString<128> UB;
- UB += "-outputs=";
for (unsigned I = 0; I < Outputs.size(); ++I) {
- if (I)
- UB += ',';
+ SmallString<128> UB;
+ UB += "-output=";
UB += DepInfo[I].DependentToolChain->getInputFilename(Outputs[I]);
+ CmdArgs.push_back(TCArgs.MakeArgString(UB));
}
- CmdArgs.push_back(TCArgs.MakeArgString(UB));
CmdArgs.push_back("-unbundle");
CmdArgs.push_back("-allow-missing-bundles");
+ if (TCArgs.hasArg(options::OPT_v))
+ CmdArgs.push_back("-verbose");
// All the inputs are encoded as commands.
C.addCommand(std::make_unique<Command>(
JA, *this, ResponseFileSupport::None(),
TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())),
- CmdArgs, None, Outputs));
+ CmdArgs, std::nullopt, Outputs));
}
-void OffloadWrapper::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void OffloadPackager::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &Args,
+ const char *LinkingOutput) const {
ArgStringList CmdArgs;
- const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
-
- // Add the "effective" target triple.
- CmdArgs.push_back("-target");
- CmdArgs.push_back(Args.MakeArgString(Triple.getTriple()));
-
// Add the output file name.
assert(Output.isFilename() && "Invalid output.");
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- // Add inputs.
- for (const InputInfo &I : Inputs) {
- assert(I.isFilename() && "Invalid input.");
- CmdArgs.push_back(I.getFilename());
+ // Create the inputs to bundle the needed metadata.
+ for (const InputInfo &Input : Inputs) {
+ const Action *OffloadAction = Input.getAction();
+ const ToolChain *TC = OffloadAction->getOffloadingToolChain();
+ const ArgList &TCArgs =
+ C.getArgsForToolChain(TC, OffloadAction->getOffloadingArch(),
+ OffloadAction->getOffloadingDeviceKind());
+ StringRef File = C.getArgs().MakeArgString(TC->getInputFilename(Input));
+ StringRef Arch = OffloadAction->getOffloadingArch()
+ ? OffloadAction->getOffloadingArch()
+ : TCArgs.getLastArgValue(options::OPT_march_EQ);
+ StringRef Kind =
+ Action::GetOffloadKindName(OffloadAction->getOffloadingDeviceKind());
+
+ ArgStringList Features;
+ SmallVector<StringRef> FeatureArgs;
+ getTargetFeatures(TC->getDriver(), TC->getTriple(), TCArgs, Features,
+ false);
+ llvm::copy_if(Features, std::back_inserter(FeatureArgs),
+ [](StringRef Arg) { return !Arg.starts_with("-target"); });
+
+ if (TC->getTriple().isAMDGPU()) {
+ for (StringRef Feature : llvm::split(Arch.split(':').second, ':')) {
+ FeatureArgs.emplace_back(
+ Args.MakeArgString(Feature.take_back() + Feature.drop_back()));
+ }
+ }
+
+ // TODO: We need to pass in the full target-id and handle it properly in the
+ // linker wrapper.
+ SmallVector<std::string> Parts{
+ "file=" + File.str(),
+ "triple=" + TC->getTripleString(),
+ "arch=" + Arch.str(),
+ "kind=" + Kind.str(),
+ };
+
+ if (TC->getDriver().isUsingLTO(/* IsOffload */ true) ||
+ TC->getTriple().isAMDGPU())
+ for (StringRef Feature : FeatureArgs)
+ Parts.emplace_back("feature=" + Feature.str());
+
+ CmdArgs.push_back(Args.MakeArgString("--image=" + llvm::join(Parts, ",")));
}
C.addCommand(std::make_unique<Command>(
@@ -7809,3 +8779,125 @@ void OffloadWrapper::ConstructJob(Compilation &C, const JobAction &JA,
Args.MakeArgString(getToolChain().GetProgramPath(getShortName())),
CmdArgs, Inputs, Output));
}
+
+void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const Driver &D = getToolChain().getDriver();
+ const llvm::Triple TheTriple = getToolChain().getTriple();
+ ArgStringList CmdArgs;
+
+ // Pass the CUDA path to the linker wrapper tool.
+ for (Action::OffloadKind Kind : {Action::OFK_Cuda, Action::OFK_OpenMP}) {
+ auto TCRange = C.getOffloadToolChains(Kind);
+ for (auto &I : llvm::make_range(TCRange.first, TCRange.second)) {
+ const ToolChain *TC = I.second;
+ if (TC->getTriple().isNVPTX()) {
+ CudaInstallationDetector CudaInstallation(D, TheTriple, Args);
+ if (CudaInstallation.isValid())
+ CmdArgs.push_back(Args.MakeArgString(
+ "--cuda-path=" + CudaInstallation.getInstallPath()));
+ break;
+ }
+ }
+ }
+
+ // Pass in the optimization level to use for LTO.
+ if (const Arg *A = Args.getLastArg(options::OPT_O_Group)) {
+ StringRef OOpt;
+ if (A->getOption().matches(options::OPT_O4) ||
+ A->getOption().matches(options::OPT_Ofast))
+ OOpt = "3";
+ else if (A->getOption().matches(options::OPT_O)) {
+ OOpt = A->getValue();
+ if (OOpt == "g")
+ OOpt = "1";
+ else if (OOpt == "s" || OOpt == "z")
+ OOpt = "2";
+ } else if (A->getOption().matches(options::OPT_O0))
+ OOpt = "0";
+ if (!OOpt.empty())
+ CmdArgs.push_back(Args.MakeArgString(Twine("--opt-level=O") + OOpt));
+ }
+
+ CmdArgs.push_back(
+ Args.MakeArgString("--host-triple=" + TheTriple.getTriple()));
+ if (Args.hasArg(options::OPT_v))
+ CmdArgs.push_back("--wrapper-verbose");
+
+ if (const Arg *A = Args.getLastArg(options::OPT_g_Group)) {
+ if (!A->getOption().matches(options::OPT_g0))
+ CmdArgs.push_back("--device-debug");
+ }
+
+ // code-object-version=X needs to be passed to clang-linker-wrapper to ensure
+ // that it is used by lld.
+ if (const Arg *A = Args.getLastArg(options::OPT_mcode_object_version_EQ)) {
+ CmdArgs.push_back(Args.MakeArgString("-mllvm"));
+ CmdArgs.push_back(Args.MakeArgString(
+ Twine("--amdhsa-code-object-version=") + A->getValue()));
+ }
+
+ for (const auto &A : Args.getAllArgValues(options::OPT_Xcuda_ptxas))
+ CmdArgs.push_back(Args.MakeArgString("--ptxas-arg=" + A));
+
+ // Forward remarks passes to the LLVM backend in the wrapper.
+ if (const Arg *A = Args.getLastArg(options::OPT_Rpass_EQ))
+ CmdArgs.push_back(Args.MakeArgString(Twine("--offload-opt=-pass-remarks=") +
+ A->getValue()));
+ if (const Arg *A = Args.getLastArg(options::OPT_Rpass_missed_EQ))
+ CmdArgs.push_back(Args.MakeArgString(
+ Twine("--offload-opt=-pass-remarks-missed=") + A->getValue()));
+ if (const Arg *A = Args.getLastArg(options::OPT_Rpass_analysis_EQ))
+ CmdArgs.push_back(Args.MakeArgString(
+ Twine("--offload-opt=-pass-remarks-analysis=") + A->getValue()));
+ if (Args.getLastArg(options::OPT_save_temps_EQ))
+ CmdArgs.push_back("--save-temps");
+
+ // Construct the link job so we can wrap around it.
+ Linker->ConstructJob(C, JA, Output, Inputs, Args, LinkingOutput);
+ const auto &LinkCommand = C.getJobs().getJobs().back();
+
+ // Forward -Xoffload-linker<-triple> arguments to the device link job.
+ for (Arg *A : Args.filtered(options::OPT_Xoffload_linker)) {
+ StringRef Val = A->getValue(0);
+ if (Val.empty())
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("--device-linker=") + A->getValue(1)));
+ else
+ CmdArgs.push_back(Args.MakeArgString(
+ "--device-linker=" +
+ ToolChain::getOpenMPTriple(Val.drop_front()).getTriple() + "=" +
+ A->getValue(1)));
+ }
+ Args.ClaimAllArgs(options::OPT_Xoffload_linker);
+
+ // Embed bitcode instead of an object in JIT mode.
+ if (Args.hasFlag(options::OPT_fopenmp_target_jit,
+ options::OPT_fno_openmp_target_jit, false))
+ CmdArgs.push_back("--embed-bitcode");
+
+ // Forward `-mllvm` arguments to the LLVM invocations if present.
+ for (Arg *A : Args.filtered(options::OPT_mllvm)) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back(A->getValue());
+ A->claim();
+ }
+
+ // Add the linker arguments to be forwarded by the wrapper.
+ CmdArgs.push_back(Args.MakeArgString(Twine("--linker-path=") +
+ LinkCommand->getExecutable()));
+ CmdArgs.push_back("--");
+ for (const char *LinkArg : LinkCommand->getArguments())
+ CmdArgs.push_back(LinkArg);
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("clang-linker-wrapper"));
+
+ // Replace the executable and arguments of the link job with the
+ // wrapper.
+ LinkCommand->replaceExecutable(Exec);
+ LinkCommand->replaceArguments(CmdArgs);
+}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.h
index d4b4988b4a8c..0f503c4bd1c4 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.h
@@ -6,17 +6,17 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Clang_H
-#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Clang_H
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CLANG_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CLANG_H
#include "MSVC.h"
-#include "clang/Basic/DebugInfoOptions.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/Types.h"
-#include "llvm/ADT/Triple.h"
+#include "llvm/Frontend/Debug/Options.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/TargetParser/Triple.h"
namespace clang {
class ObjCRuntime;
@@ -26,6 +26,10 @@ namespace tools {
/// Clang compiler tool.
class LLVM_LIBRARY_VISIBILITY Clang : public Tool {
+ // Indicates whether this instance has integrated backend using
+ // internal LLVM infrastructure.
+ bool HasBackend;
+
public:
static const char *getBaseInputName(const llvm::opt::ArgList &Args,
const InputInfo &Input);
@@ -53,6 +57,8 @@ private:
bool KernelOrKext) const;
void AddARM64TargetArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
+ void AddLoongArchTargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
void AddMIPSTargetArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
void AddPPCTargetArgs(const llvm::opt::ArgList &Args,
@@ -84,9 +90,7 @@ private:
RewriteKind rewrite) const;
void AddClangCLArgs(const llvm::opt::ArgList &Args, types::ID InputType,
- llvm::opt::ArgStringList &CmdArgs,
- codegenoptions::DebugInfoKind *DebugInfoKind,
- bool *EmitCodeView) const;
+ llvm::opt::ArgStringList &CmdArgs) const;
mutable std::unique_ptr<llvm::raw_fd_ostream> CompilationDatabase = nullptr;
void DumpCompilationDatabase(Compilation &C, StringRef Filename,
@@ -99,11 +103,12 @@ private:
const InputInfo &Input, const llvm::opt::ArgList &Args) const;
public:
- Clang(const ToolChain &TC);
+ Clang(const ToolChain &TC, bool HasIntegratedBackend = true);
~Clang() override;
bool hasGoodDiagnostics() const override { return true; }
bool hasIntegratedAssembler() const override { return true; }
+ bool hasIntegratedBackend() const override { return HasBackend; }
bool hasIntegratedCPP() const override { return true; }
bool canEmitIR() const override { return true; }
@@ -118,6 +123,8 @@ class LLVM_LIBRARY_VISIBILITY ClangAs : public Tool {
public:
ClangAs(const ToolChain &TC)
: Tool("clang::as", "clang integrated assembler", TC) {}
+ void AddLoongArchTargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
void AddMIPSTargetArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
void AddX86TargetArgs(const llvm::opt::ArgList &Args,
@@ -152,11 +159,11 @@ public:
const char *LinkingOutput) const override;
};
-/// Offload wrapper tool.
-class LLVM_LIBRARY_VISIBILITY OffloadWrapper final : public Tool {
+/// Offload binary tool.
+class LLVM_LIBRARY_VISIBILITY OffloadPackager final : public Tool {
public:
- OffloadWrapper(const ToolChain &TC)
- : Tool("offload wrapper", "clang-offload-wrapper", TC) {}
+ OffloadPackager(const ToolChain &TC)
+ : Tool("Offload::Packager", "clang-offload-packager", TC) {}
bool hasIntegratedCPP() const override { return false; }
void ConstructJob(Compilation &C, const JobAction &JA,
@@ -165,6 +172,27 @@ public:
const char *LinkingOutput) const override;
};
+/// Linker wrapper tool.
+class LLVM_LIBRARY_VISIBILITY LinkerWrapper final : public Tool {
+ const Tool *Linker;
+
+public:
+ LinkerWrapper(const ToolChain &TC, const Tool *Linker)
+ : Tool("Offload::Linker", "linker", TC), Linker(Linker) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
+enum class DwarfFissionKind { None, Split, Single };
+
+DwarfFissionKind getDebugFissionKind(const Driver &D,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::Arg *&Arg);
+
} // end namespace tools
} // end namespace driver
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/CloudABI.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/CloudABI.cpp
deleted file mode 100644
index 9ee46ac857f0..000000000000
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/CloudABI.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-//===--- CloudABI.cpp - CloudABI ToolChain Implementations ------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "CloudABI.h"
-#include "CommonArgs.h"
-#include "clang/Driver/Compilation.h"
-#include "clang/Driver/Driver.h"
-#include "clang/Driver/InputInfo.h"
-#include "clang/Driver/Options.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/Option/ArgList.h"
-#include "llvm/Support/Path.h"
-
-using namespace clang::driver;
-using namespace clang::driver::tools;
-using namespace clang::driver::toolchains;
-using namespace clang;
-using namespace llvm::opt;
-
-void cloudabi::Linker::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
- const ToolChain &ToolChain = getToolChain();
- const Driver &D = ToolChain.getDriver();
- ArgStringList CmdArgs;
-
- // 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);
-
- if (!D.SysRoot.empty())
- CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
-
- // CloudABI only supports static linkage.
- CmdArgs.push_back("-Bstatic");
- CmdArgs.push_back("--no-dynamic-linker");
-
- // Provide PIE linker flags in case PIE is default for the architecture.
- if (ToolChain.isPIEDefault()) {
- CmdArgs.push_back("-pie");
- CmdArgs.push_back("-zrelro");
- }
-
- CmdArgs.push_back("--eh-frame-hdr");
- CmdArgs.push_back("--gc-sections");
-
- if (Output.isFilename()) {
- CmdArgs.push_back("-o");
- CmdArgs.push_back(Output.getFilename());
- } else {
- assert(Output.isNothing() && "Invalid output.");
- }
-
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o")));
- }
-
- Args.AddAllArgs(CmdArgs, options::OPT_L);
- ToolChain.AddFilePathLibArgs(Args, CmdArgs);
- Args.AddAllArgs(CmdArgs,
- {options::OPT_T_Group, options::OPT_e, options::OPT_s,
- options::OPT_t, options::OPT_Z_Flag, options::OPT_r});
-
- if (D.isUsingLTO()) {
- assert(!Inputs.empty() && "Must have at least one input.");
- addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs[0],
- D.getLTOMode() == LTOK_Thin);
- }
-
- AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
-
- if (ToolChain.ShouldLinkCXXStdlib(Args))
- ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
- CmdArgs.push_back("-lc");
- CmdArgs.push_back("-lcompiler_rt");
- }
-
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
-
- const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
- C.addCommand(std::make_unique<Command>(JA, *this,
- ResponseFileSupport::AtFileCurCP(),
- Exec, CmdArgs, Inputs, Output));
-}
-
-// CloudABI - CloudABI tool chain which can call ld(1) directly.
-
-CloudABI::CloudABI(const Driver &D, const llvm::Triple &Triple,
- const ArgList &Args)
- : Generic_ELF(D, Triple, Args) {
- SmallString<128> P(getDriver().Dir);
- llvm::sys::path::append(P, "..", getTriple().str(), "lib");
- getFilePaths().push_back(std::string(P.str()));
-}
-
-void CloudABI::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const {
- SmallString<128> P(getDriver().Dir);
- llvm::sys::path::append(P, "..", getTriple().str(), "include/c++/v1");
- addSystemInclude(DriverArgs, CC1Args, P.str());
-}
-
-void CloudABI::AddCXXStdlibLibArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const {
- CmdArgs.push_back("-lc++");
- CmdArgs.push_back("-lc++abi");
- CmdArgs.push_back("-lunwind");
-}
-
-Tool *CloudABI::buildLinker() const {
- return new tools::cloudabi::Linker(*this);
-}
-
-bool CloudABI::isPIEDefault() 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.
- switch (getTriple().getArch()) {
- case llvm::Triple::aarch64:
- case llvm::Triple::x86_64:
- return true;
- default:
- return false;
- }
-}
-
-SanitizerMask CloudABI::getSupportedSanitizers() const {
- SanitizerMask Res = ToolChain::getSupportedSanitizers();
- Res |= SanitizerKind::SafeStack;
- return Res;
-}
-
-SanitizerMask CloudABI::getDefaultSanitizers() const {
- return SanitizerKind::SafeStack;
-}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/CloudABI.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/CloudABI.h
deleted file mode 100644
index 98bf23127706..000000000000
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/CloudABI.h
+++ /dev/null
@@ -1,70 +0,0 @@
-//===--- CloudABI.h - CloudABI ToolChain Implementations --------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CLOUDABI_H
-#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CLOUDABI_H
-
-#include "Gnu.h"
-#include "clang/Driver/Tool.h"
-#include "clang/Driver/ToolChain.h"
-
-namespace clang {
-namespace driver {
-namespace tools {
-
-/// cloudabi -- Directly call GNU Binutils linker
-namespace cloudabi {
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
-public:
- Linker(const ToolChain &TC) : Tool("cloudabi::Linker", "linker", TC) {}
-
- bool hasIntegratedCPP() const override { return false; }
- bool isLinkJob() const override { return true; }
-
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
-};
-} // end namespace cloudabi
-} // end namespace tools
-
-namespace toolchains {
-
-class LLVM_LIBRARY_VISIBILITY CloudABI : public Generic_ELF {
-public:
- CloudABI(const Driver &D, const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args);
- bool HasNativeLLVMSupport() const override { return true; }
-
- bool IsMathErrnoDefault() const override { return false; }
- bool IsObjCNonFragileABIDefault() const override { return true; }
-
- CXXStdlibType
- GetCXXStdlibType(const llvm::opt::ArgList &Args) const override {
- return ToolChain::CST_Libcxx;
- }
- void addLibCxxIncludePaths(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
- void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const override;
-
- bool isPIEDefault() const override;
- SanitizerMask getSupportedSanitizers() const override;
- SanitizerMask getDefaultSanitizers() const override;
-
-protected:
- Tool *buildLinker() const override;
-};
-
-} // end namespace toolchains
-} // end namespace driver
-} // end namespace clang
-
-#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CLOUDABI_H
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 0ffe95795381..2b916f000336 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -9,15 +9,22 @@
#include "CommonArgs.h"
#include "Arch/AArch64.h"
#include "Arch/ARM.h"
+#include "Arch/CSKY.h"
+#include "Arch/LoongArch.h"
#include "Arch/M68k.h"
#include "Arch/Mips.h"
#include "Arch/PPC.h"
+#include "Arch/RISCV.h"
+#include "Arch/Sparc.h"
#include "Arch/SystemZ.h"
#include "Arch/VE.h"
#include "Arch/X86.h"
-#include "HIP.h"
+#include "HIPAMD.h"
#include "Hexagon.h"
+#include "MSP430.h"
+#include "Solaris.h"
#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Version.h"
@@ -34,10 +41,12 @@
#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"
#include "llvm/ADT/Twine.h"
+#include "llvm/BinaryFormat/Magic.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
@@ -47,39 +56,180 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/ScopedPrinter.h"
-#include "llvm/Support/TargetParser.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/YAMLParser.h"
+#include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/TargetParser.h"
+#include <optional>
using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;
-static void renderRpassOptions(const ArgList &Args, ArgStringList &CmdArgs) {
+static bool useFramePointerForTargetByDefault(const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple) {
+ if (Args.hasArg(clang::driver::options::OPT_pg) &&
+ !Args.hasArg(clang::driver::options::OPT_mfentry))
+ return true;
+
+ if (Triple.isAndroid()) {
+ switch (Triple.getArch()) {
+ case llvm::Triple::aarch64:
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ case llvm::Triple::riscv64:
+ return true;
+ default:
+ break;
+ }
+ }
+
+ switch (Triple.getArch()) {
+ case llvm::Triple::xcore:
+ case llvm::Triple::wasm32:
+ case llvm::Triple::wasm64:
+ case llvm::Triple::msp430:
+ // XCore never wants frame pointers, regardless of OS.
+ // WebAssembly never wants frame pointers.
+ return false;
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppcle:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ case llvm::Triple::sparc:
+ case llvm::Triple::sparcel:
+ case llvm::Triple::sparcv9:
+ case llvm::Triple::amdgcn:
+ case llvm::Triple::r600:
+ case llvm::Triple::csky:
+ case llvm::Triple::loongarch32:
+ case llvm::Triple::loongarch64:
+ return !clang::driver::tools::areOptimizationsEnabled(Args);
+ default:
+ break;
+ }
+
+ if (Triple.isOSFuchsia() || Triple.isOSNetBSD()) {
+ return !clang::driver::tools::areOptimizationsEnabled(Args);
+ }
+
+ if (Triple.isOSLinux() || Triple.isOSHurd()) {
+ switch (Triple.getArch()) {
+ // Don't use a frame pointer on linux if optimizing for certain targets.
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::systemz:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ return !clang::driver::tools::areOptimizationsEnabled(Args);
+ default:
+ return true;
+ }
+ }
+
+ if (Triple.isOSWindows()) {
+ switch (Triple.getArch()) {
+ case llvm::Triple::x86:
+ return !clang::driver::tools::areOptimizationsEnabled(Args);
+ case llvm::Triple::x86_64:
+ return Triple.isOSBinFormatMachO();
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ // Windows on ARM builds with FPO disabled to aid fast stack walking
+ return true;
+ default:
+ // All other supported Windows ISAs use xdata unwind information, so frame
+ // pointers are not generally useful.
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool mustUseNonLeafFramePointerForTarget(const llvm::Triple &Triple) {
+ switch (Triple.getArch()) {
+ default:
+ return false;
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ // ARM Darwin targets require a frame pointer to be always present to aid
+ // offline debugging via backtraces.
+ return Triple.isOSDarwin();
+ }
+}
+
+clang::CodeGenOptions::FramePointerKind
+getFramePointerKind(const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple) {
+ // We have 4 states:
+ //
+ // 00) leaf retained, non-leaf retained
+ // 01) leaf retained, non-leaf omitted (this is invalid)
+ // 10) leaf omitted, non-leaf retained
+ // (what -momit-leaf-frame-pointer was designed for)
+ // 11) leaf omitted, non-leaf omitted
+ //
+ // "omit" options taking precedence over "no-omit" options is the only way
+ // to make 3 valid states representable
+ llvm::opt::Arg *A =
+ Args.getLastArg(clang::driver::options::OPT_fomit_frame_pointer,
+ clang::driver::options::OPT_fno_omit_frame_pointer);
+
+ bool OmitFP = A && A->getOption().matches(
+ clang::driver::options::OPT_fomit_frame_pointer);
+ bool NoOmitFP = A && A->getOption().matches(
+ clang::driver::options::OPT_fno_omit_frame_pointer);
+ bool OmitLeafFP =
+ Args.hasFlag(clang::driver::options::OPT_momit_leaf_frame_pointer,
+ clang::driver::options::OPT_mno_omit_leaf_frame_pointer,
+ Triple.isAArch64() || Triple.isPS() || Triple.isVE() ||
+ (Triple.isAndroid() && Triple.isRISCV64()));
+ if (NoOmitFP || mustUseNonLeafFramePointerForTarget(Triple) ||
+ (!OmitFP && useFramePointerForTargetByDefault(Args, Triple))) {
+ if (OmitLeafFP)
+ return clang::CodeGenOptions::FramePointerKind::NonLeaf;
+ return clang::CodeGenOptions::FramePointerKind::All;
+ }
+ return clang::CodeGenOptions::FramePointerKind::None;
+}
+
+static void renderRpassOptions(const ArgList &Args, ArgStringList &CmdArgs,
+ const StringRef PluginOptPrefix) {
if (const Arg *A = Args.getLastArg(options::OPT_Rpass_EQ))
- CmdArgs.push_back(Args.MakeArgString(Twine("--plugin-opt=-pass-remarks=") +
- A->getValue()));
+ CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
+ "-pass-remarks=" + A->getValue()));
if (const Arg *A = Args.getLastArg(options::OPT_Rpass_missed_EQ))
CmdArgs.push_back(Args.MakeArgString(
- Twine("--plugin-opt=-pass-remarks-missed=") + A->getValue()));
+ Twine(PluginOptPrefix) + "-pass-remarks-missed=" + A->getValue()));
if (const Arg *A = Args.getLastArg(options::OPT_Rpass_analysis_EQ))
CmdArgs.push_back(Args.MakeArgString(
- Twine("--plugin-opt=-pass-remarks-analysis=") + A->getValue()));
+ Twine(PluginOptPrefix) + "-pass-remarks-analysis=" + A->getValue()));
}
static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs,
const llvm::Triple &Triple,
const InputInfo &Input,
- const InputInfo &Output) {
+ const InputInfo &Output,
+ const StringRef PluginOptPrefix) {
StringRef Format = "yaml";
if (const Arg *A = Args.getLastArg(options::OPT_fsave_optimization_record_EQ))
Format = A->getValue();
@@ -93,29 +243,47 @@ static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs,
assert(!F.empty() && "Cannot determine remarks output name.");
// Append "opt.ld.<format>" to the end of the file name.
- CmdArgs.push_back(
- Args.MakeArgString(Twine("--plugin-opt=opt-remarks-filename=") + F +
- Twine(".opt.ld.") + Format));
+ CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
+ "opt-remarks-filename=" + F +
+ ".opt.ld." + Format));
if (const Arg *A =
Args.getLastArg(options::OPT_foptimization_record_passes_EQ))
CmdArgs.push_back(Args.MakeArgString(
- Twine("--plugin-opt=opt-remarks-passes=") + A->getValue()));
+ Twine(PluginOptPrefix) + "opt-remarks-passes=" + A->getValue()));
- CmdArgs.push_back(Args.MakeArgString(
- Twine("--plugin-opt=opt-remarks-format=") + Format.data()));
+ CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
+ "opt-remarks-format=" + Format.data()));
}
static void renderRemarksHotnessOptions(const ArgList &Args,
- ArgStringList &CmdArgs) {
+ ArgStringList &CmdArgs,
+ const StringRef PluginOptPrefix) {
if (Args.hasFlag(options::OPT_fdiagnostics_show_hotness,
options::OPT_fno_diagnostics_show_hotness, false))
- CmdArgs.push_back("--plugin-opt=opt-remarks-with-hotness");
+ CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
+ "opt-remarks-with-hotness"));
if (const Arg *A =
Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ))
- CmdArgs.push_back(Args.MakeArgString(
- Twine("--plugin-opt=opt-remarks-hotness-threshold=") + A->getValue()));
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine(PluginOptPrefix) +
+ "opt-remarks-hotness-threshold=" + A->getValue()));
+}
+
+static bool shouldIgnoreUnsupportedTargetFeature(const Arg &TargetFeatureArg,
+ llvm::Triple T,
+ StringRef Processor) {
+ // Warn no-cumode for AMDGCN processors not supporing WGP mode.
+ if (!T.isAMDGPU())
+ return false;
+ auto GPUKind = T.isAMDGCN() ? llvm::AMDGPU::parseArchAMDGCN(Processor)
+ : llvm::AMDGPU::parseArchR600(Processor);
+ auto GPUFeatures = T.isAMDGCN() ? llvm::AMDGPU::getArchAttrAMDGCN(GPUKind)
+ : llvm::AMDGPU::getArchAttrR600(GPUKind);
+ if (GPUFeatures & llvm::AMDGPU::FEATURE_WGP)
+ return false;
+ return TargetFeatureArg.getOption().matches(options::OPT_mno_cumode);
}
void tools::addPathIfExists(const Driver &D, const Twine &Path,
@@ -124,46 +292,49 @@ void tools::addPathIfExists(const Driver &D, const Twine &Path,
Paths.push_back(Path.str());
}
-void tools::handleTargetFeaturesGroup(const ArgList &Args,
+void tools::handleTargetFeaturesGroup(const Driver &D,
+ const llvm::Triple &Triple,
+ const ArgList &Args,
std::vector<StringRef> &Features,
OptSpecifier Group) {
+ std::set<StringRef> Warned;
for (const Arg *A : Args.filtered(Group)) {
StringRef Name = A->getOption().getName();
A->claim();
// Skip over "-m".
- assert(Name.startswith("m") && "Invalid feature name.");
+ assert(Name.starts_with("m") && "Invalid feature name.");
Name = Name.substr(1);
- bool IsNegative = Name.startswith("no-");
+ auto Proc = getCPUName(D, Args, Triple);
+ if (shouldIgnoreUnsupportedTargetFeature(*A, Triple, Proc)) {
+ if (Warned.count(Name) == 0) {
+ D.getDiags().Report(
+ clang::diag::warn_drv_unsupported_option_for_processor)
+ << A->getAsString(Args) << Proc;
+ Warned.insert(Name);
+ }
+ continue;
+ }
+
+ bool IsNegative = Name.starts_with("no-");
if (IsNegative)
Name = Name.substr(3);
+
Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
}
}
-std::vector<StringRef>
-tools::unifyTargetFeatures(const std::vector<StringRef> &Features) {
- std::vector<StringRef> UnifiedFeatures;
- // Find the last of each feature.
- llvm::StringMap<unsigned> LastOpt;
- for (unsigned I = 0, N = Features.size(); I < N; ++I) {
- StringRef Name = Features[I];
- assert(Name[0] == '-' || Name[0] == '+');
- LastOpt[Name.drop_front(1)] = I;
+SmallVector<StringRef>
+tools::unifyTargetFeatures(ArrayRef<StringRef> Features) {
+ // Only add a feature if it hasn't been seen before starting from the end.
+ SmallVector<StringRef> UnifiedFeatures;
+ llvm::DenseSet<StringRef> UsedFeatures;
+ for (StringRef Feature : llvm::reverse(Features)) {
+ if (UsedFeatures.insert(Feature.drop_front()).second)
+ UnifiedFeatures.insert(UnifiedFeatures.begin(), Feature);
}
- for (unsigned I = 0, N = Features.size(); I < N; ++I) {
- // If this feature was overridden, ignore it.
- StringRef Name = Features[I];
- llvm::StringMap<unsigned>::iterator LastI = LastOpt.find(Name.drop_front(1));
- assert(LastI != LastOpt.end());
- unsigned Last = LastI->second;
- if (Last != I)
- continue;
-
- UnifiedFeatures.push_back(Name);
- }
return UnifiedFeatures;
}
@@ -254,6 +425,10 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs,
continue;
}
+ // In some error cases, the input could be Nothing; skip those.
+ if (II.isNothing())
+ continue;
+
// Otherwise, this is a linker input argument.
const Arg &A = II.getInputArg();
@@ -262,13 +437,8 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs,
TC.AddCXXStdlibLibArgs(Args, CmdArgs);
else if (A.getOption().matches(options::OPT_Z_reserved_lib_cckext))
TC.AddCCKextLibArgs(Args, CmdArgs);
- else if (A.getOption().matches(options::OPT_z)) {
- // Pass -z prefix for gcc linker compatibility.
- A.claim();
- A.render(Args, CmdArgs);
- } else {
+ else
A.renderAsInput(Args, CmdArgs);
- }
}
}
@@ -276,17 +446,17 @@ void tools::addLinkerCompressDebugSectionsOption(
const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) {
// GNU ld supports --compress-debug-sections=none|zlib|zlib-gnu|zlib-gabi
- // whereas zlib is an alias to zlib-gabi. Therefore -gz=none|zlib|zlib-gnu
- // are translated to --compress-debug-sections=none|zlib|zlib-gnu.
- // -gz is not translated since ld --compress-debug-sections option requires an
+ // whereas zlib is an alias to zlib-gabi and zlib-gnu is obsoleted. Therefore
+ // -gz=none|zlib are translated to --compress-debug-sections=none|zlib. -gz
+ // is not translated since ld --compress-debug-sections option requires an
// argument.
if (const Arg *A = Args.getLastArg(options::OPT_gz_EQ)) {
StringRef V = A->getValue();
- if (V == "none" || V == "zlib" || V == "zlib-gnu")
+ if (V == "none" || V == "zlib" || V == "zstd")
CmdArgs.push_back(Args.MakeArgString("--compress-debug-sections=" + V));
else
TC.getDriver().Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << V;
+ << A->getSpelling() << V;
}
}
@@ -305,6 +475,7 @@ void tools::AddTargetFeature(const ArgList &Args,
/// Get the (LLVM) name of the AMDGPU gpu we are targeting.
static std::string getAMDGPUTargetGPU(const llvm::Triple &T,
const ArgList &Args) {
+ Arg *MArch = Args.getLastArg(options::OPT_march_EQ);
if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
auto GPUName = getProcessorFromTargetID(T, A->getValue());
return llvm::StringSwitch<std::string>(GPUName)
@@ -317,6 +488,8 @@ static std::string getAMDGPUTargetGPU(const llvm::Triple &T,
.Case("aruba", "cayman")
.Default(GPUName.str());
}
+ if (MArch)
+ return getProcessorFromTargetID(T, MArch->getValue()).str();
return "";
}
@@ -346,8 +519,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()) {
@@ -395,50 +568,34 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T,
case llvm::Triple::ppc:
case llvm::Triple::ppcle:
case llvm::Triple::ppc64:
- case llvm::Triple::ppc64le: {
- std::string TargetCPUName = ppc::getPPCTargetCPU(Args);
- // LLVM may default to generating code for the native CPU,
- // but, like gcc, we default to a more generic option for
- // each architecture. (except on AIX)
- 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)
- TargetCPUName = "ppc64le";
- else if (T.getArch() == llvm::Triple::ppc64)
- TargetCPUName = "ppc64";
- else
- TargetCPUName = "ppc";
+ case llvm::Triple::ppc64le:
+ return ppc::getPPCTargetCPU(D, Args, T);
- return TargetCPUName;
- }
+ case llvm::Triple::csky:
+ if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
+ return A->getValue();
+ else if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
+ return A->getValue();
+ else
+ return "ck810";
case llvm::Triple::riscv32:
case llvm::Triple::riscv64:
+ return riscv::getRISCVTargetCPU(Args, T);
+
+ case llvm::Triple::bpfel:
+ case llvm::Triple::bpfeb:
if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
return A->getValue();
return "";
- case llvm::Triple::bpfel:
- case llvm::Triple::bpfeb:
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
case llvm::Triple::sparcv9:
- if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
- return A->getValue();
- if (T.getArch() == llvm::Triple::sparc && T.isOSSolaris())
- return "v9";
- return "";
+ return sparc::getSparcTargetCPU(D, Args, 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" +
@@ -457,6 +614,103 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T,
case llvm::Triple::wasm32:
case llvm::Triple::wasm64:
return std::string(getWebAssemblyTargetCPU(Args));
+
+ case llvm::Triple::loongarch32:
+ case llvm::Triple::loongarch64:
+ return loongarch::getLoongArchTargetCPU(Args, T);
+ }
+}
+
+static void getWebAssemblyTargetFeatures(const Driver &D,
+ const llvm::Triple &Triple,
+ const ArgList &Args,
+ std::vector<StringRef> &Features) {
+ handleTargetFeaturesGroup(D, Triple, Args, Features,
+ options::OPT_m_wasm_Features_Group);
+}
+
+void tools::getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args, ArgStringList &CmdArgs,
+ bool ForAS, bool IsAux) {
+ std::vector<StringRef> Features;
+ switch (Triple.getArch()) {
+ default:
+ break;
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ mips::getMIPSTargetFeatures(D, Triple, Args, Features);
+ break;
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ arm::getARMTargetFeatures(D, Triple, Args, Features, ForAS);
+ break;
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppcle:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
+ ppc::getPPCTargetFeatures(D, Triple, Args, Features);
+ break;
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ riscv::getRISCVTargetFeatures(D, Triple, Args, Features);
+ break;
+ case llvm::Triple::systemz:
+ systemz::getSystemZTargetFeatures(D, Args, Features);
+ break;
+ case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_32:
+ case llvm::Triple::aarch64_be:
+ aarch64::getAArch64TargetFeatures(D, Triple, Args, Features, ForAS);
+ break;
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ x86::getX86TargetFeatures(D, Triple, Args, Features);
+ break;
+ case llvm::Triple::hexagon:
+ hexagon::getHexagonTargetFeatures(D, Triple, Args, Features);
+ break;
+ case llvm::Triple::wasm32:
+ case llvm::Triple::wasm64:
+ getWebAssemblyTargetFeatures(D, Triple, Args, Features);
+ break;
+ case llvm::Triple::sparc:
+ case llvm::Triple::sparcel:
+ case llvm::Triple::sparcv9:
+ sparc::getSparcTargetFeatures(D, Args, Features);
+ break;
+ case llvm::Triple::r600:
+ case llvm::Triple::amdgcn:
+ amdgpu::getAMDGPUTargetFeatures(D, Triple, Args, Features);
+ break;
+ case llvm::Triple::nvptx:
+ case llvm::Triple::nvptx64:
+ NVPTX::getNVPTXTargetFeatures(D, Triple, Args, Features);
+ break;
+ case llvm::Triple::m68k:
+ m68k::getM68kTargetFeatures(D, Triple, Args, Features);
+ break;
+ case llvm::Triple::msp430:
+ msp430::getMSP430TargetFeatures(D, Args, Features);
+ break;
+ case llvm::Triple::ve:
+ ve::getVETargetFeatures(D, Args, Features);
+ break;
+ case llvm::Triple::csky:
+ csky::getCSKYTargetFeatures(D, Triple, Args, CmdArgs, Features);
+ break;
+ case llvm::Triple::loongarch32:
+ case llvm::Triple::loongarch64:
+ loongarch::getLoongArchTargetFeatures(D, Triple, Args, Features);
+ break;
+ }
+
+ for (auto Feature : unifyTargetFeatures(Features)) {
+ CmdArgs.push_back(IsAux ? "-aux-target-feature" : "-target-feature");
+ CmdArgs.push_back(Feature.data());
}
}
@@ -470,22 +724,58 @@ llvm::StringRef tools::getLTOParallelism(const ArgList &Args, const Driver &D) {
return LtoJobsArg->getValue();
}
-// CloudABI uses -ffunction-sections and -fdata-sections by default.
+// PS4/PS5 uses -ffunction-sections and -fdata-sections by default.
bool tools::isUseSeparateSections(const llvm::Triple &Triple) {
- return Triple.getOS() == llvm::Triple::CloudABI;
+ return Triple.isPS();
+}
+
+bool tools::isTLSDESCEnabled(const ToolChain &TC,
+ const llvm::opt::ArgList &Args) {
+ const llvm::Triple &Triple = TC.getEffectiveTriple();
+ Arg *A = Args.getLastArg(options::OPT_mtls_dialect_EQ);
+ if (!A)
+ return Triple.hasDefaultTLSDESC();
+ StringRef V = A->getValue();
+ bool SupportedArgument = false, EnableTLSDESC = false;
+ bool Unsupported = !Triple.isOSBinFormatELF();
+ if (Triple.isRISCV()) {
+ SupportedArgument = V == "desc" || V == "trad";
+ EnableTLSDESC = V == "desc";
+ } else if (Triple.isX86()) {
+ SupportedArgument = V == "gnu";
+ } else {
+ Unsupported = true;
+ }
+ if (Unsupported) {
+ TC.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getSpelling() << Triple.getTriple();
+ } else if (!SupportedArgument) {
+ TC.getDriver().Diag(diag::err_drv_unsupported_option_argument_for_target)
+ << A->getSpelling() << V << Triple.getTriple();
+ }
+ return EnableTLSDESC;
}
void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,
ArgStringList &CmdArgs, const InputInfo &Output,
const InputInfo &Input, bool IsThinLTO) {
+ const bool IsOSAIX = ToolChain.getTriple().isOSAIX();
+ const bool IsAMDGCN = ToolChain.getTriple().isAMDGCN();
const char *Linker = Args.MakeArgString(ToolChain.GetLinkerPath());
const Driver &D = ToolChain.getDriver();
+ const bool IsFatLTO = Args.hasArg(options::OPT_ffat_lto_objects);
+ const bool IsUnifiedLTO = Args.hasArg(options::OPT_funified_lto);
if (llvm::sys::path::filename(Linker) != "ld.lld" &&
- llvm::sys::path::stem(Linker) != "ld.lld") {
+ llvm::sys::path::stem(Linker) != "ld.lld" &&
+ !ToolChain.getTriple().isOSOpenBSD()) {
// Tell the linker to load the plugin. This has to come before
- // AddLinkerInputs as gold requires -plugin to come before any -plugin-opt
- // that -Wl might forward.
- CmdArgs.push_back("-plugin");
+ // AddLinkerInputs as gold requires -plugin and AIX ld requires -bplugin to
+ // come before any -plugin-opt/-bplugin_opt that -Wl might forward.
+ const char *PluginPrefix = IsOSAIX ? "-bplugin:" : "";
+ const char *PluginName = IsOSAIX ? "/libLTO" : "/LLVMgold";
+
+ if (!IsOSAIX)
+ CmdArgs.push_back("-plugin");
#if defined(_WIN32)
const char *Suffix = ".dll";
@@ -496,19 +786,60 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,
#endif
SmallString<1024> Plugin;
- llvm::sys::path::native(
- Twine(D.Dir) + "/../lib" CLANG_LIBDIR_SUFFIX "/LLVMgold" + Suffix,
- Plugin);
- CmdArgs.push_back(Args.MakeArgString(Plugin));
+ llvm::sys::path::native(Twine(D.Dir) +
+ "/../" CLANG_INSTALL_LIBDIR_BASENAME +
+ PluginName + Suffix,
+ Plugin);
+ CmdArgs.push_back(Args.MakeArgString(Twine(PluginPrefix) + Plugin));
+ } else {
+ // Tell LLD to find and use .llvm.lto section in regular relocatable object
+ // files
+ if (IsFatLTO)
+ CmdArgs.push_back("--fat-lto-objects");
+ }
+
+ const char *PluginOptPrefix = IsOSAIX ? "-bplugin_opt:" : "-plugin-opt=";
+ const char *ExtraDash = IsOSAIX ? "-" : "";
+ const char *ParallelismOpt = IsOSAIX ? "-threads=" : "jobs=";
+
+ // Note, this solution is far from perfect, better to encode it into IR
+ // metadata, but this may not be worth it, since it looks like aranges is on
+ // the way out.
+ if (Args.hasArg(options::OPT_gdwarf_aranges)) {
+ CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
+ "-generate-arange-section"));
+ }
+
+ // Pass vector library arguments to LTO.
+ Arg *ArgVecLib = Args.getLastArg(options::OPT_fveclib);
+ if (ArgVecLib && ArgVecLib->getNumValues() == 1) {
+ // Map the vector library names from clang front-end to opt front-end. The
+ // values are taken from the TargetLibraryInfo class command line options.
+ std::optional<StringRef> OptVal =
+ llvm::StringSwitch<std::optional<StringRef>>(ArgVecLib->getValue())
+ .Case("Accelerate", "Accelerate")
+ .Case("LIBMVEC", "LIBMVEC-X86")
+ .Case("MASSV", "MASSV")
+ .Case("SVML", "SVML")
+ .Case("SLEEF", "sleefgnuabi")
+ .Case("Darwin_libsystem_m", "Darwin_libsystem_m")
+ .Case("ArmPL", "ArmPL")
+ .Case("none", "none")
+ .Default(std::nullopt);
+
+ if (OptVal)
+ CmdArgs.push_back(Args.MakeArgString(
+ Twine(PluginOptPrefix) + "-vector-library=" + OptVal.value()));
}
// Try to pass driver level flags relevant to LTO code generation down to
// 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));
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash + "mcpu=" + CPU));
if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
// The optimization level matches
@@ -525,48 +856,140 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,
OOpt = "2";
} else if (A->getOption().matches(options::OPT_O0))
OOpt = "0";
- if (!OOpt.empty())
- CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=O") + OOpt));
+ if (!OOpt.empty()) {
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash + "O" + OOpt));
+ if (IsAMDGCN)
+ CmdArgs.push_back(Args.MakeArgString(Twine("--lto-CGO") + OOpt));
+ }
}
- if (Args.hasArg(options::OPT_gsplit_dwarf)) {
+ if (Args.hasArg(options::OPT_gsplit_dwarf))
+ CmdArgs.push_back(Args.MakeArgString(
+ Twine(PluginOptPrefix) + "dwo_dir=" + Output.getFilename() + "_dwo"));
+
+ if (IsThinLTO && !IsOSAIX)
+ CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + "thinlto"));
+ else if (IsThinLTO && IsOSAIX)
+ CmdArgs.push_back(Args.MakeArgString(Twine("-bdbg:thinlto")));
+
+ // Matrix intrinsic lowering happens at link time with ThinLTO. Enable
+ // LowerMatrixIntrinsicsPass, which is transitively called by
+ // buildThinLTODefaultPipeline under EnableMatrix.
+ if ((IsThinLTO || IsFatLTO || IsUnifiedLTO) &&
+ Args.hasArg(options::OPT_fenable_matrix))
CmdArgs.push_back(
- Args.MakeArgString(Twine("-plugin-opt=dwo_dir=") +
- Output.getFilename() + "_dwo"));
- }
-
- if (IsThinLTO)
- CmdArgs.push_back("-plugin-opt=thinlto");
+ Args.MakeArgString(Twine(PluginOptPrefix) + "-enable-matrix"));
StringRef Parallelism = getLTOParallelism(Args, D);
if (!Parallelism.empty())
- CmdArgs.push_back(
- Args.MakeArgString("-plugin-opt=jobs=" + Twine(Parallelism)));
+ CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
+ ParallelismOpt + Parallelism));
+
+ // Pass down GlobalISel options.
+ if (Arg *A = Args.getLastArg(options::OPT_fglobal_isel,
+ options::OPT_fno_global_isel)) {
+ // Parsing -fno-global-isel explicitly gives architectures that enable GISel
+ // by default a chance to disable it.
+ CmdArgs.push_back(Args.MakeArgString(
+ Twine(PluginOptPrefix) + "-global-isel=" +
+ (A->getOption().matches(options::OPT_fglobal_isel) ? "1" : "0")));
+ }
// If an explicit debugger tuning argument appeared, pass it along.
- if (Arg *A = Args.getLastArg(options::OPT_gTune_Group,
- options::OPT_ggdbN_Group)) {
+ if (Arg *A =
+ Args.getLastArg(options::OPT_gTune_Group, options::OPT_ggdbN_Group)) {
if (A->getOption().matches(options::OPT_glldb))
- CmdArgs.push_back("-plugin-opt=-debugger-tune=lldb");
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine(PluginOptPrefix) + "-debugger-tune=lldb"));
else if (A->getOption().matches(options::OPT_gsce))
- CmdArgs.push_back("-plugin-opt=-debugger-tune=sce");
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine(PluginOptPrefix) + "-debugger-tune=sce"));
else if (A->getOption().matches(options::OPT_gdbx))
- CmdArgs.push_back("-plugin-opt=-debugger-tune=dbx");
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine(PluginOptPrefix) + "-debugger-tune=dbx"));
else
- CmdArgs.push_back("-plugin-opt=-debugger-tune=gdb");
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine(PluginOptPrefix) + "-debugger-tune=gdb"));
+ }
+
+ if (IsOSAIX) {
+ if (!ToolChain.useIntegratedAs())
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine(PluginOptPrefix) + "-no-integrated-as=1"));
+
+ // On AIX, clang assumes strict-dwarf is true if any debug option is
+ // specified, unless it is told explicitly not to assume so.
+ Arg *A = Args.getLastArg(options::OPT_g_Group);
+ bool EnableDebugInfo = A && !A->getOption().matches(options::OPT_g0) &&
+ !A->getOption().matches(options::OPT_ggdb0);
+ if (EnableDebugInfo && Args.hasFlag(options::OPT_gstrict_dwarf,
+ options::OPT_gno_strict_dwarf, true))
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine(PluginOptPrefix) + "-strict-dwarf=true"));
+
+ for (const Arg *A : Args.filtered_reverse(options::OPT_mabi_EQ)) {
+ StringRef V = A->getValue();
+ if (V == "vec-default")
+ break;
+ if (V == "vec-extabi") {
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine(PluginOptPrefix) + "-vec-extabi"));
+ break;
+ }
+ }
}
bool UseSeparateSections =
isUseSeparateSections(ToolChain.getEffectiveTriple());
if (Args.hasFlag(options::OPT_ffunction_sections,
- options::OPT_fno_function_sections, UseSeparateSections)) {
- CmdArgs.push_back("-plugin-opt=-function-sections");
- }
+ options::OPT_fno_function_sections, UseSeparateSections))
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine(PluginOptPrefix) + "-function-sections=1"));
+ else if (Args.hasArg(options::OPT_fno_function_sections))
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine(PluginOptPrefix) + "-function-sections=0"));
+ bool DataSectionsTurnedOff = false;
if (Args.hasFlag(options::OPT_fdata_sections, options::OPT_fno_data_sections,
UseSeparateSections)) {
- CmdArgs.push_back("-plugin-opt=-data-sections");
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine(PluginOptPrefix) + "-data-sections=1"));
+ } else if (Args.hasArg(options::OPT_fno_data_sections)) {
+ DataSectionsTurnedOff = true;
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine(PluginOptPrefix) + "-data-sections=0"));
+ }
+
+ if (Args.hasArg(options::OPT_mxcoff_roptr) ||
+ Args.hasArg(options::OPT_mno_xcoff_roptr)) {
+ bool HasRoptr = Args.hasFlag(options::OPT_mxcoff_roptr,
+ options::OPT_mno_xcoff_roptr, false);
+ StringRef OptStr = HasRoptr ? "-mxcoff-roptr" : "-mno-xcoff-roptr";
+
+ if (!IsOSAIX)
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << OptStr << ToolChain.getTriple().str();
+
+ if (HasRoptr) {
+ // The data sections option is on by default on AIX. We only need to error
+ // out when -fno-data-sections is specified explicitly to turn off data
+ // sections.
+ if (DataSectionsTurnedOff)
+ D.Diag(diag::err_roptr_requires_data_sections);
+
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine(PluginOptPrefix) + "-mxcoff-roptr"));
+ }
+ }
+
+ // Pass an option to enable split machine functions.
+ if (auto *A = Args.getLastArg(options::OPT_fsplit_machine_functions,
+ options::OPT_fno_split_machine_functions)) {
+ if (A->getOption().matches(options::OPT_fsplit_machine_functions))
+ CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
+ "-split-machine-functions"));
}
if (Arg *A = getLastProfileSampleUseArg(Args)) {
@@ -574,90 +997,126 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,
if (!llvm::sys::fs::exists(FName))
D.Diag(diag::err_drv_no_such_file) << FName;
else
- CmdArgs.push_back(
- Args.MakeArgString(Twine("-plugin-opt=sample-profile=") + FName));
+ CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
+ "sample-profile=" + FName));
}
- auto *CSPGOGenerateArg = Args.getLastArg(options::OPT_fcs_profile_generate,
- options::OPT_fcs_profile_generate_EQ,
- options::OPT_fno_profile_generate);
- if (CSPGOGenerateArg &&
- CSPGOGenerateArg->getOption().matches(options::OPT_fno_profile_generate))
- CSPGOGenerateArg = nullptr;
-
- auto *ProfileUseArg = getLastProfileUseArg(Args);
-
- if (CSPGOGenerateArg) {
- CmdArgs.push_back(Args.MakeArgString("-plugin-opt=cs-profile-generate"));
+ if (auto *CSPGOGenerateArg = getLastCSProfileGenerateArg(Args)) {
+ CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash +
+ "cs-profile-generate"));
if (CSPGOGenerateArg->getOption().matches(
options::OPT_fcs_profile_generate_EQ)) {
SmallString<128> Path(CSPGOGenerateArg->getValue());
llvm::sys::path::append(Path, "default_%m.profraw");
- CmdArgs.push_back(
- Args.MakeArgString(Twine("-plugin-opt=cs-profile-path=") + Path));
+ CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash +
+ "cs-profile-path=" + Path));
} else
CmdArgs.push_back(
- Args.MakeArgString("-plugin-opt=cs-profile-path=default_%m.profraw"));
- } else if (ProfileUseArg) {
+ Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash +
+ "cs-profile-path=default_%m.profraw"));
+ } else if (auto *ProfileUseArg = getLastProfileUseArg(Args)) {
SmallString<128> Path(
ProfileUseArg->getNumValues() == 0 ? "" : ProfileUseArg->getValue());
if (Path.empty() || llvm::sys::fs::is_directory(Path))
llvm::sys::path::append(Path, "default.profdata");
- CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=cs-profile-path=") +
- Path));
+ CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash +
+ "cs-profile-path=" + Path));
}
- // Pass an option to enable/disable the new pass manager.
- if (auto *A = Args.getLastArg(options::OPT_flegacy_pass_manager,
- options::OPT_fno_legacy_pass_manager)) {
- if (A->getOption().matches(options::OPT_flegacy_pass_manager))
- CmdArgs.push_back("-plugin-opt=legacy-pass-manager");
+ // This controls whether or not we perform JustMyCode instrumentation.
+ if (Args.hasFlag(options::OPT_fjmc, options::OPT_fno_jmc, false)) {
+ if (ToolChain.getEffectiveTriple().isOSBinFormatELF())
+ CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) +
+ "-enable-jmc-instrument"));
else
- CmdArgs.push_back("-plugin-opt=new-pass-manager");
+ D.Diag(clang::diag::warn_drv_fjmc_for_elf_only);
+ }
+
+ if (Args.hasFlag(options::OPT_femulated_tls, options::OPT_fno_emulated_tls,
+ ToolChain.getTriple().hasDefaultEmulatedTLS())) {
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine(PluginOptPrefix) + "-emulated-tls"));
}
+ if (isTLSDESCEnabled(ToolChain, Args))
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine(PluginOptPrefix) + "-enable-tlsdesc"));
- // 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");
+ if (Args.hasFlag(options::OPT_fstack_size_section,
+ options::OPT_fno_stack_size_section, false))
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine(PluginOptPrefix) + "-stack-size-section"));
// Setup statistics file output.
SmallString<128> StatsFile = getStatsFileName(Args, Output, Input, D);
if (!StatsFile.empty())
CmdArgs.push_back(
- Args.MakeArgString(Twine("-plugin-opt=stats-file=") + StatsFile));
+ Args.MakeArgString(Twine(PluginOptPrefix) + "stats-file=" + StatsFile));
+
+ // Setup crash diagnostics dir.
+ if (Arg *A = Args.getLastArg(options::OPT_fcrash_diagnostics_dir))
+ CmdArgs.push_back(Args.MakeArgString(
+ Twine(PluginOptPrefix) + "-crash-diagnostics-dir=" + A->getValue()));
- addX86AlignBranchArgs(D, Args, CmdArgs, /*IsLTO=*/true);
+ addX86AlignBranchArgs(D, Args, CmdArgs, /*IsLTO=*/true, PluginOptPrefix);
// Handle remark diagnostics on screen options: '-Rpass-*'.
- renderRpassOptions(Args, CmdArgs);
+ renderRpassOptions(Args, CmdArgs, PluginOptPrefix);
// Handle serialized remarks options: '-fsave-optimization-record'
// and '-foptimization-record-*'.
if (willEmitRemarks(Args))
renderRemarksOptions(Args, CmdArgs, ToolChain.getEffectiveTriple(), Input,
- Output);
+ Output, PluginOptPrefix);
// Handle remarks hotness/threshold related options.
- renderRemarksHotnessOptions(Args, CmdArgs);
+ renderRemarksHotnessOptions(Args, CmdArgs, PluginOptPrefix);
addMachineOutlinerArgs(D, Args, CmdArgs, ToolChain.getEffectiveTriple(),
- /*IsLTO=*/true);
+ /*IsLTO=*/true, PluginOptPrefix);
+}
+
+/// Adds the '-lcgpu' and '-lmgpu' libraries to the compilation to include the
+/// LLVM C library for GPUs.
+static void addOpenMPDeviceLibC(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ if (Args.hasArg(options::OPT_nogpulib) || Args.hasArg(options::OPT_nolibc))
+ return;
+
+ // Check the resource directory for the LLVM libc GPU declarations. If it's
+ // found we can assume that LLVM was built with support for the GPU libc.
+ SmallString<256> LibCDecls(TC.getDriver().ResourceDir);
+ llvm::sys::path::append(LibCDecls, "include", "llvm_libc_wrappers",
+ "llvm-libc-decls");
+ bool HasLibC = llvm::sys::fs::exists(LibCDecls) &&
+ llvm::sys::fs::is_directory(LibCDecls);
+ if (Args.hasFlag(options::OPT_gpulibc, options::OPT_nogpulibc, HasLibC)) {
+ CmdArgs.push_back("-lcgpu");
+ CmdArgs.push_back("-lmgpu");
+ }
+}
+
+void tools::addOpenMPRuntimeLibraryPath(const ToolChain &TC,
+ const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ // Default to clang lib / lib64 folder, i.e. the same location as device
+ // runtime.
+ SmallString<256> DefaultLibPath =
+ llvm::sys::path::parent_path(TC.getDriver().Dir);
+ llvm::sys::path::append(DefaultLibPath, CLANG_INSTALL_LIBDIR_BASENAME);
+ CmdArgs.push_back(Args.MakeArgString("-L" + DefaultLibPath));
}
void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
- // Enable -frtlib-add-rpath by default for the case of VE.
- const bool IsVE = TC.getTriple().isVE();
- bool DefaultValue = IsVE;
if (!Args.hasFlag(options::OPT_frtlib_add_rpath,
- options::OPT_fno_rtlib_add_rpath, DefaultValue))
+ options::OPT_fno_rtlib_add_rpath, false))
return;
- std::string CandidateRPath = TC.getArchSpecificLibPath();
- if (TC.getVFS().exists(CandidateRPath)) {
- CmdArgs.push_back("-rpath");
- CmdArgs.push_back(Args.MakeArgString(CandidateRPath.c_str()));
+ for (const auto &CandidateRPath : TC.getArchSpecificLibPaths()) {
+ if (TC.getVFS().exists(CandidateRPath)) {
+ CmdArgs.push_back("-rpath");
+ CmdArgs.push_back(Args.MakeArgString(CandidateRPath));
+ }
}
}
@@ -700,11 +1159,155 @@ bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
if (IsOffloadingHost)
CmdArgs.push_back("-lomptarget");
+ if (IsOffloadingHost && !Args.hasArg(options::OPT_nogpulib))
+ CmdArgs.push_back("-lomptarget.devicertl");
+
+ if (IsOffloadingHost)
+ addOpenMPDeviceLibC(TC, Args, CmdArgs);
+
addArchSpecificRPath(TC, Args, CmdArgs);
+ addOpenMPRuntimeLibraryPath(TC, Args, CmdArgs);
return true;
}
+/// Determines if --whole-archive is active in the list of arguments.
+static bool isWholeArchivePresent(const ArgList &Args) {
+ bool WholeArchiveActive = false;
+ for (auto *Arg : Args.filtered(options::OPT_Wl_COMMA)) {
+ if (Arg) {
+ for (StringRef ArgValue : Arg->getValues()) {
+ if (ArgValue == "--whole-archive")
+ WholeArchiveActive = true;
+ if (ArgValue == "--no-whole-archive")
+ WholeArchiveActive = false;
+ }
+ }
+ }
+
+ return WholeArchiveActive;
+}
+
+/// Determine if driver is invoked to create a shared object library (-static)
+static bool isSharedLinkage(const ArgList &Args) {
+ return Args.hasArg(options::OPT_shared);
+}
+
+/// Determine if driver is invoked to create a static object library (-shared)
+static bool isStaticLinkage(const ArgList &Args) {
+ return Args.hasArg(options::OPT_static);
+}
+
+/// Add Fortran runtime libs for MSVC
+static void addFortranRuntimeLibsMSVC(const ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) {
+ unsigned RTOptionID = options::OPT__SLASH_MT;
+ if (auto *rtl = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
+ RTOptionID = llvm::StringSwitch<unsigned>(rtl->getValue())
+ .Case("static", options::OPT__SLASH_MT)
+ .Case("static_dbg", options::OPT__SLASH_MTd)
+ .Case("dll", options::OPT__SLASH_MD)
+ .Case("dll_dbg", options::OPT__SLASH_MDd)
+ .Default(options::OPT__SLASH_MT);
+ }
+ switch (RTOptionID) {
+ case options::OPT__SLASH_MT:
+ CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static.lib");
+ break;
+ case options::OPT__SLASH_MTd:
+ CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static_dbg.lib");
+ break;
+ case options::OPT__SLASH_MD:
+ CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic.lib");
+ break;
+ case options::OPT__SLASH_MDd:
+ CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic_dbg.lib");
+ break;
+ }
+}
+
+// Add FortranMain runtime lib
+static void addFortranMain(const ToolChain &TC, const ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) {
+ // 0. Shared-library linkage
+ // If we are attempting to link a library, we should not add
+ // -lFortran_main.a to the link line, as the `main` symbol is not
+ // required for a library and should also be provided by one of
+ // the translation units of the code that this shared library
+ // will be linked against eventually.
+ if (isSharedLinkage(Args) || isStaticLinkage(Args)) {
+ return;
+ }
+
+ // 1. MSVC
+ if (TC.getTriple().isKnownWindowsMSVCEnvironment()) {
+ addFortranRuntimeLibsMSVC(Args, CmdArgs);
+ return;
+ }
+
+ // 2. GNU and similar
+ const Driver &D = TC.getDriver();
+ const char *FortranMainLinkFlag = "-lFortran_main";
+
+ // Warn if the user added `-lFortran_main` - this library is an implementation
+ // detail of Flang and should be handled automaticaly by the driver.
+ for (const char *arg : CmdArgs) {
+ if (strncmp(arg, FortranMainLinkFlag, strlen(FortranMainLinkFlag)) == 0)
+ D.Diag(diag::warn_drv_deprecated_custom)
+ << FortranMainLinkFlag
+ << "see the Flang driver documentation for correct usage";
+ }
+
+ // The --whole-archive option needs to be part of the link line to make
+ // sure that the main() function from Fortran_main.a is pulled in by the
+ // linker. However, it shouldn't be used if it's already active.
+ // TODO: Find an equivalent of `--whole-archive` for Darwin and AIX.
+ if (!isWholeArchivePresent(Args) && !TC.getTriple().isMacOSX() &&
+ !TC.getTriple().isOSAIX()) {
+ CmdArgs.push_back("--whole-archive");
+ CmdArgs.push_back(FortranMainLinkFlag);
+ CmdArgs.push_back("--no-whole-archive");
+ return;
+ }
+
+ CmdArgs.push_back(FortranMainLinkFlag);
+}
+
+/// Add Fortran runtime libs
+void tools::addFortranRuntimeLibs(const ToolChain &TC, const ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) {
+ // 1. Link FortranMain
+ // FortranMain depends on FortranRuntime, so needs to be listed first. If
+ // -fno-fortran-main has been passed, skip linking Fortran_main.a
+ if (!Args.hasArg(options::OPT_no_fortran_main))
+ addFortranMain(TC, Args, CmdArgs);
+
+ // 2. Link FortranRuntime and FortranDecimal
+ // These are handled earlier on Windows by telling the frontend driver to
+ // add the correct libraries to link against as dependents in the object
+ // file.
+ if (!TC.getTriple().isKnownWindowsMSVCEnvironment()) {
+ CmdArgs.push_back("-lFortranRuntime");
+ CmdArgs.push_back("-lFortranDecimal");
+ }
+}
+
+void tools::addFortranRuntimeLibraryPath(const ToolChain &TC,
+ const llvm::opt::ArgList &Args,
+ ArgStringList &CmdArgs) {
+ // Default to the <driver-path>/../lib directory. This works fine on the
+ // platforms that we have tested so far. We will probably have to re-fine
+ // this in the future. In particular, on some platforms, we may need to use
+ // lib64 instead of lib.
+ SmallString<256> DefaultLibPath =
+ llvm::sys::path::parent_path(TC.getDriver().Dir);
+ llvm::sys::path::append(DefaultLibPath, "lib");
+ if (TC.getTriple().isKnownWindowsMSVCEnvironment())
+ CmdArgs.push_back(Args.MakeArgString("-libpath:" + DefaultLibPath));
+ else
+ CmdArgs.push_back(Args.MakeArgString("-L" + DefaultLibPath));
+}
+
static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs, StringRef Sanitizer,
bool IsShared, bool IsWhole) {
@@ -725,9 +1328,11 @@ static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args,
static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs,
StringRef Sanitizer) {
+ bool LinkerIsGnuLd = solaris::isLinkerGnuLd(TC, Args);
+
// Solaris ld defaults to --export-dynamic behaviour but doesn't support
// the option, so don't try to pass it.
- if (TC.getTriple().getOS() == llvm::Triple::Solaris)
+ if (TC.getTriple().isOSSolaris() && !LinkerIsGnuLd)
return true;
SmallString<128> SanRT(TC.getCompilerRT(Args, Sanitizer));
if (llvm::sys::fs::exists(SanRT + ".syms")) {
@@ -737,32 +1342,36 @@ static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args,
return false;
}
-static const char *getAsNeededOption(const ToolChain &TC, bool as_needed) {
+void tools::addAsNeededOption(const ToolChain &TC,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs,
+ bool as_needed) {
assert(!TC.getTriple().isOSAIX() &&
"AIX linker does not support any form of --as-needed option yet.");
+ bool LinkerIsGnuLd = solaris::isLinkerGnuLd(TC, Args);
// While the Solaris 11.2 ld added --as-needed/--no-as-needed as aliases
// for the native forms -z ignore/-z record, they are missing in Illumos,
// so always use the native form.
- if (TC.getTriple().isOSSolaris())
- return as_needed ? "-zignore" : "-zrecord";
- else
- return as_needed ? "--as-needed" : "--no-as-needed";
+ // GNU ld doesn't support -z ignore/-z record, so don't use them even on
+ // Solaris.
+ if (TC.getTriple().isOSSolaris() && !LinkerIsGnuLd) {
+ CmdArgs.push_back("-z");
+ CmdArgs.push_back(as_needed ? "ignore" : "record");
+ } else {
+ CmdArgs.push_back(as_needed ? "--as-needed" : "--no-as-needed");
+ }
}
void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
+ const llvm::opt::ArgList &Args,
ArgStringList &CmdArgs) {
- // Fuchsia never needs these. Any sanitizer runtimes with system
- // dependencies use the `.deplibs` feature instead.
- if (TC.getTriple().isOSFuchsia())
- return;
-
// Force linking against the system libraries sanitizers depends on
// (see PR15823 why this is necessary).
- CmdArgs.push_back(getAsNeededOption(TC, false));
+ addAsNeededOption(TC, Args, CmdArgs, false);
// There's no libpthread or librt on RTEMS & Android.
if (TC.getTriple().getOS() != llvm::Triple::RTEMS &&
- !TC.getTriple().isAndroid()) {
+ !TC.getTriple().isAndroid() && !TC.getTriple().isOHOSFamily()) {
CmdArgs.push_back("-lpthread");
if (!TC.getTriple().isOSOpenBSD())
CmdArgs.push_back("-lrt");
@@ -778,6 +1387,12 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
TC.getTriple().isOSNetBSD() ||
TC.getTriple().isOSOpenBSD())
CmdArgs.push_back("-lexecinfo");
+ // There is no libresolv on Android, FreeBSD, OpenBSD, etc. On musl
+ // libresolv.a, even if exists, is an empty archive to satisfy POSIX -lresolv
+ // requirement.
+ if (TC.getTriple().isOSLinux() && !TC.getTriple().isAndroid() &&
+ !TC.getTriple().isMusl())
+ CmdArgs.push_back("-lresolv");
}
static void
@@ -787,45 +1402,48 @@ 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()) {
+ if (SanArgs.needsAsanRt()) {
SharedRuntimes.push_back("asan");
if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid())
HelperStaticRuntimes.push_back("asan-preinit");
}
- if (SanArgs.needsMemProfRt() && SanArgs.linkRuntimes()) {
+ if (SanArgs.needsMemProfRt()) {
SharedRuntimes.push_back("memprof");
if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid())
HelperStaticRuntimes.push_back("memprof-preinit");
}
- if (SanArgs.needsUbsanRt() && SanArgs.linkRuntimes()) {
+ if (SanArgs.needsUbsanRt()) {
if (SanArgs.requiresMinimalRuntime())
SharedRuntimes.push_back("ubsan_minimal");
else
SharedRuntimes.push_back("ubsan_standalone");
}
- if (SanArgs.needsScudoRt() && SanArgs.linkRuntimes()) {
- if (SanArgs.requiresMinimalRuntime())
- SharedRuntimes.push_back("scudo_minimal");
- else
- SharedRuntimes.push_back("scudo");
+ if (SanArgs.needsScudoRt()) {
+ SharedRuntimes.push_back("scudo_standalone");
}
- if (SanArgs.needsTsanRt() && SanArgs.linkRuntimes())
+ if (SanArgs.needsTsanRt())
SharedRuntimes.push_back("tsan");
- if (SanArgs.needsHwasanRt() && SanArgs.linkRuntimes()) {
+ if (SanArgs.needsHwasanRt()) {
if (SanArgs.needsHwasanAliasesRt())
SharedRuntimes.push_back("hwasan_aliases");
else
SharedRuntimes.push_back("hwasan");
+ if (!Args.hasArg(options::OPT_shared))
+ HelperStaticRuntimes.push_back("hwasan-preinit");
}
}
// The stats_client library is also statically linked into DSOs.
- if (SanArgs.needsStatsRt() && SanArgs.linkRuntimes())
+ if (SanArgs.needsStatsRt())
StaticRuntimes.push_back("stats_client");
+ // Always link the static runtime regardless of DSO or executable.
+ if (SanArgs.needsAsanRt())
+ HelperStaticRuntimes.push_back("asan_static");
+
// Collect static runtimes.
if (Args.hasArg(options::OPT_shared)) {
// Don't link static runtimes into DSOs.
@@ -835,20 +1453,19 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
// Each static runtime that has a DSO counterpart above is excluded below,
// but runtimes that exist only as static are not affected by needsSharedRt.
- if (!SanArgs.needsSharedRt() && SanArgs.needsAsanRt() && SanArgs.linkRuntimes()) {
+ if (!SanArgs.needsSharedRt() && SanArgs.needsAsanRt()) {
StaticRuntimes.push_back("asan");
if (SanArgs.linkCXXRuntimes())
StaticRuntimes.push_back("asan_cxx");
}
- if (!SanArgs.needsSharedRt() && SanArgs.needsMemProfRt() &&
- SanArgs.linkRuntimes()) {
+ if (!SanArgs.needsSharedRt() && SanArgs.needsMemProfRt()) {
StaticRuntimes.push_back("memprof");
if (SanArgs.linkCXXRuntimes())
StaticRuntimes.push_back("memprof_cxx");
}
- if (!SanArgs.needsSharedRt() && SanArgs.needsHwasanRt() && SanArgs.linkRuntimes()) {
+ if (!SanArgs.needsSharedRt() && SanArgs.needsHwasanRt()) {
if (SanArgs.needsHwasanAliasesRt()) {
StaticRuntimes.push_back("hwasan_aliases");
if (SanArgs.linkCXXRuntimes())
@@ -859,22 +1476,21 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
StaticRuntimes.push_back("hwasan_cxx");
}
}
- if (SanArgs.needsDfsanRt() && SanArgs.linkRuntimes())
+ if (SanArgs.needsDfsanRt())
StaticRuntimes.push_back("dfsan");
- if (SanArgs.needsLsanRt() && SanArgs.linkRuntimes())
+ if (SanArgs.needsLsanRt())
StaticRuntimes.push_back("lsan");
- if (SanArgs.needsMsanRt() && SanArgs.linkRuntimes()) {
+ if (SanArgs.needsMsanRt()) {
StaticRuntimes.push_back("msan");
if (SanArgs.linkCXXRuntimes())
StaticRuntimes.push_back("msan_cxx");
}
- if (!SanArgs.needsSharedRt() && SanArgs.needsTsanRt() &&
- SanArgs.linkRuntimes()) {
+ if (!SanArgs.needsSharedRt() && SanArgs.needsTsanRt()) {
StaticRuntimes.push_back("tsan");
if (SanArgs.linkCXXRuntimes())
StaticRuntimes.push_back("tsan_cxx");
}
- if (!SanArgs.needsSharedRt() && SanArgs.needsUbsanRt() && SanArgs.linkRuntimes()) {
+ if (!SanArgs.needsSharedRt() && SanArgs.needsUbsanRt()) {
if (SanArgs.requiresMinimalRuntime()) {
StaticRuntimes.push_back("ubsan_minimal");
} else {
@@ -883,33 +1499,27 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
StaticRuntimes.push_back("ubsan_standalone_cxx");
}
}
- if (SanArgs.needsSafeStackRt() && SanArgs.linkRuntimes()) {
+ if (SanArgs.needsSafeStackRt()) {
NonWholeStaticRuntimes.push_back("safestack");
RequiredSymbols.push_back("__safestack_init");
}
- if (!(SanArgs.needsSharedRt() && SanArgs.needsUbsanRt() && SanArgs.linkRuntimes())) {
- if (SanArgs.needsCfiRt() && SanArgs.linkRuntimes())
+ if (!(SanArgs.needsSharedRt() && SanArgs.needsUbsanRt())) {
+ if (SanArgs.needsCfiRt())
StaticRuntimes.push_back("cfi");
- if (SanArgs.needsCfiDiagRt() && SanArgs.linkRuntimes()) {
+ if (SanArgs.needsCfiDiagRt()) {
StaticRuntimes.push_back("cfi_diag");
if (SanArgs.linkCXXRuntimes())
StaticRuntimes.push_back("ubsan_standalone_cxx");
}
}
- if (SanArgs.needsStatsRt() && SanArgs.linkRuntimes()) {
+ if (SanArgs.needsStatsRt()) {
NonWholeStaticRuntimes.push_back("stats");
RequiredSymbols.push_back("__sanitizer_stats_register");
}
- if (!SanArgs.needsSharedRt() && SanArgs.needsScudoRt() && SanArgs.linkRuntimes()) {
- if (SanArgs.requiresMinimalRuntime()) {
- StaticRuntimes.push_back("scudo_minimal");
- if (SanArgs.linkCXXRuntimes())
- StaticRuntimes.push_back("scudo_cxx_minimal");
- } else {
- StaticRuntimes.push_back("scudo");
- if (SanArgs.linkCXXRuntimes())
- StaticRuntimes.push_back("scudo_cxx");
- }
+ if (!SanArgs.needsSharedRt() && SanArgs.needsScudoRt()) {
+ StaticRuntimes.push_back("scudo_standalone");
+ if (SanArgs.linkCXXRuntimes())
+ StaticRuntimes.push_back("scudo_standalone_cxx");
}
}
@@ -917,13 +1527,15 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
// C runtime, etc). Returns true if sanitizer system deps need to be linked in.
bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
+ const SanitizerArgs &SanArgs = TC.getSanitizerArgs(Args);
SmallVector<StringRef, 4> SharedRuntimes, StaticRuntimes,
NonWholeStaticRuntimes, HelperStaticRuntimes, RequiredSymbols;
- collectSanitizerRuntimes(TC, Args, SharedRuntimes, StaticRuntimes,
- NonWholeStaticRuntimes, HelperStaticRuntimes,
- RequiredSymbols);
+ if (SanArgs.linkRuntimes()) {
+ collectSanitizerRuntimes(TC, Args, SharedRuntimes, StaticRuntimes,
+ NonWholeStaticRuntimes, HelperStaticRuntimes,
+ RequiredSymbols);
+ }
- const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
// Inject libfuzzer dependencies.
if (SanArgs.needsFuzzer() && SanArgs.linkRuntimes() &&
!Args.hasArg(options::OPT_shared)) {
@@ -968,6 +1580,19 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
if (SanArgs.hasCrossDsoCfi() && !AddExportDynamic)
CmdArgs.push_back("--export-dynamic-symbol=__cfi_check");
+ if (SanArgs.hasMemTag()) {
+ if (!TC.getTriple().isAndroid()) {
+ TC.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
+ << "-fsanitize=memtag*" << TC.getTriple().str();
+ }
+ CmdArgs.push_back(
+ Args.MakeArgString("--android-memtag-mode=" + SanArgs.getMemtagMode()));
+ if (SanArgs.hasMemtagHeap())
+ CmdArgs.push_back("--android-memtag-heap");
+ if (SanArgs.hasMemtagStack())
+ CmdArgs.push_back("--android-memtag-stack");
+ }
+
return !StaticRuntimes.empty() || !NonWholeStaticRuntimes.empty();
}
@@ -976,19 +1601,21 @@ bool tools::addXRayRuntime(const ToolChain&TC, const ArgList &Args, ArgStringLis
return false;
if (TC.getXRayArgs().needsXRayRt()) {
- CmdArgs.push_back("-whole-archive");
+ CmdArgs.push_back("--whole-archive");
CmdArgs.push_back(TC.getCompilerRTArgString(Args, "xray"));
for (const auto &Mode : TC.getXRayArgs().modeList())
CmdArgs.push_back(TC.getCompilerRTArgString(Args, Mode));
- CmdArgs.push_back("-no-whole-archive");
+ CmdArgs.push_back("--no-whole-archive");
return true;
}
return false;
}
-void tools::linkXRayRuntimeDeps(const ToolChain &TC, ArgStringList &CmdArgs) {
- CmdArgs.push_back(getAsNeededOption(TC, false));
+void tools::linkXRayRuntimeDeps(const ToolChain &TC,
+ const llvm::opt::ArgList &Args,
+ ArgStringList &CmdArgs) {
+ addAsNeededOption(TC, Args, CmdArgs, false);
CmdArgs.push_back("-lpthread");
if (!TC.getTriple().isOSOpenBSD())
CmdArgs.push_back("-lrt");
@@ -1017,26 +1644,27 @@ const char *tools::SplitDebugName(const JobAction &JA, const ArgList &Args,
F += ".dwo";
};
if (Arg *A = Args.getLastArg(options::OPT_gsplit_dwarf_EQ))
- if (StringRef(A->getValue()) == "single")
+ if (StringRef(A->getValue()) == "single" && Output.isFilename())
return Args.MakeArgString(Output.getFilename());
- Arg *FinalOutput = Args.getLastArg(options::OPT_o);
- if (FinalOutput && Args.hasArg(options::OPT_c)) {
- SmallString<128> T(FinalOutput->getValue());
- llvm::sys::path::remove_filename(T);
- llvm::sys::path::append(T, llvm::sys::path::stem(FinalOutput->getValue()));
- AddPostfix(T);
- return Args.MakeArgString(T);
+ SmallString<128> T;
+ if (const Arg *A = Args.getLastArg(options::OPT_dumpdir)) {
+ T = A->getValue();
} else {
- // Use the compilation dir.
- Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ,
- options::OPT_fdebug_compilation_dir_EQ);
- SmallString<128> T(A ? A->getValue() : "");
- SmallString<128> F(llvm::sys::path::stem(Input.getBaseInput()));
- AddPostfix(F);
- T += F;
- return Args.MakeArgString(T);
+ Arg *FinalOutput = Args.getLastArg(options::OPT_o, options::OPT__SLASH_o);
+ if (FinalOutput && Args.hasArg(options::OPT_c)) {
+ T = FinalOutput->getValue();
+ llvm::sys::path::remove_filename(T);
+ llvm::sys::path::append(T,
+ llvm::sys::path::stem(FinalOutput->getValue()));
+ AddPostfix(T);
+ return Args.MakeArgString(T);
+ }
}
+
+ T += llvm::sys::path::stem(Input.getBaseInput());
+ AddPostfix(T);
+ return Args.MakeArgString(T);
}
void tools::SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T,
@@ -1078,6 +1706,17 @@ void tools::claimNoWarnArgs(const ArgList &Args) {
Args.ClaimAllArgs(options::OPT_fno_lto);
}
+Arg *tools::getLastCSProfileGenerateArg(const ArgList &Args) {
+ auto *CSPGOGenerateArg = Args.getLastArg(options::OPT_fcs_profile_generate,
+ options::OPT_fcs_profile_generate_EQ,
+ options::OPT_fno_profile_generate);
+ if (CSPGOGenerateArg &&
+ CSPGOGenerateArg->getOption().matches(options::OPT_fno_profile_generate))
+ CSPGOGenerateArg = nullptr;
+
+ return CSPGOGenerateArg;
+}
+
Arg *tools::getLastProfileUseArg(const ArgList &Args) {
auto *ProfileUseArg = Args.getLastArg(
options::OPT_fprofile_instr_use, options::OPT_fprofile_instr_use_EQ,
@@ -1107,6 +1746,24 @@ Arg *tools::getLastProfileSampleUseArg(const ArgList &Args) {
options::OPT_fauto_profile_EQ);
}
+const char *tools::RelocationModelName(llvm::Reloc::Model Model) {
+ switch (Model) {
+ case llvm::Reloc::Static:
+ return "static";
+ case llvm::Reloc::PIC_:
+ return "pic";
+ case llvm::Reloc::DynamicNoPIC:
+ return "dynamic-no-pic";
+ case llvm::Reloc::ROPI:
+ return "ropi";
+ case llvm::Reloc::RWPI:
+ return "rwpi";
+ case llvm::Reloc::ROPI_RWPI:
+ return "ropi-rwpi";
+ }
+ llvm_unreachable("Unknown Reloc::Model kind");
+}
+
/// Parses the various -fpic/-fPIC/-fpie/-fPIE arguments. Then,
/// smooshes them together with platform defaults, to decide whether
/// this compile should be using PIC mode or not. Returns a tuple of
@@ -1116,7 +1773,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))
@@ -1152,6 +1809,10 @@ tools::ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) {
}
}
+ // OHOS-specific defaults for PIC/PIE
+ if (Triple.isOHOSFamily() && Triple.getArch() == llvm::Triple::aarch64)
+ PIC = true;
+
// OpenBSD-specific defaults for PIE
if (Triple.isOSOpenBSD()) {
switch (ToolChain.getArch()) {
@@ -1174,10 +1835,6 @@ tools::ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) {
}
}
- // AMDGPU-specific defaults for PIC.
- if (Triple.getArch() == llvm::Triple::amdgcn)
- PIC = true;
-
// The last argument relating to either PIC or PIE wins, and no
// other argument is used. If the last argument is any flavor of the
// '-fno-...' arguments, both PIC and PIE are disabled. Any PIE
@@ -1186,10 +1843,9 @@ tools::ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) {
options::OPT_fpic, options::OPT_fno_pic,
options::OPT_fPIE, options::OPT_fno_PIE,
options::OPT_fpie, options::OPT_fno_pie);
- if (Triple.isOSWindows() && LastPICArg &&
- LastPICArg ==
- Args.getLastArg(options::OPT_fPIC, options::OPT_fpic,
- options::OPT_fPIE, options::OPT_fpie)) {
+ if (Triple.isOSWindows() && !Triple.isOSCygMing() && LastPICArg &&
+ LastPICArg == Args.getLastArg(options::OPT_fPIC, options::OPT_fpic,
+ options::OPT_fPIE, options::OPT_fpie)) {
ToolChain.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
<< LastPICArg->getSpelling() << Triple.str();
if (Triple.getArch() == llvm::Triple::x86_64)
@@ -1211,30 +1867,31 @@ tools::ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) {
O.matches(options::OPT_fPIE) || O.matches(options::OPT_fPIC);
} else {
PIE = PIC = false;
- if (EffectiveTriple.isPS4CPU()) {
+ if (EffectiveTriple.isPS()) {
Arg *ModelArg = Args.getLastArg(options::OPT_mcmodel_EQ);
StringRef Model = ModelArg ? ModelArg->getValue() : "";
if (Model != "kernel") {
PIC = true;
- ToolChain.getDriver().Diag(diag::warn_drv_ps4_force_pic)
- << LastPICArg->getSpelling();
+ ToolChain.getDriver().Diag(diag::warn_drv_ps_force_pic)
+ << LastPICArg->getSpelling()
+ << (EffectiveTriple.isPS4() ? "PS4" : "PS5");
}
}
}
}
}
- // Introduce a Darwin and PS4-specific hack. If the default is PIC, but the
- // PIC level would've been set to level 1, force it back to level 2 PIC
+ // Introduce a Darwin and PS4/PS5-specific hack. If the default is PIC, but
+ // the PIC level would've been set to level 1, force it back to level 2 PIC
// instead.
- if (PIC && (Triple.isOSDarwin() || EffectiveTriple.isPS4CPU()))
+ if (PIC && (Triple.isOSDarwin() || EffectiveTriple.isPS()))
IsPICLevelTwo |= ToolChain.isPICDefault();
// This kernel flags are a trump-card: they will disable PIC/PIE
// generation, independent of the argument order.
if (KernelOrKext &&
((!EffectiveTriple.isiOS() || EffectiveTriple.isOSVersionLT(6)) &&
- !EffectiveTriple.isWatchOS()))
+ !EffectiveTriple.isWatchOS() && !EffectiveTriple.isDriverKit()))
PIC = PIE = false;
if (Arg *A = Args.getLastArg(options::OPT_mdynamic_no_pic)) {
@@ -1352,7 +2009,49 @@ unsigned tools::ParseFunctionAlignment(const ToolChain &TC,
return Value ? llvm::Log2_32_Ceil(std::min(Value, 65536u)) : Value;
}
-unsigned tools::ParseDebugDefaultVersion(const ToolChain &TC,
+void tools::addDebugInfoKind(
+ ArgStringList &CmdArgs, llvm::codegenoptions::DebugInfoKind DebugInfoKind) {
+ switch (DebugInfoKind) {
+ case llvm::codegenoptions::DebugDirectivesOnly:
+ CmdArgs.push_back("-debug-info-kind=line-directives-only");
+ break;
+ case llvm::codegenoptions::DebugLineTablesOnly:
+ CmdArgs.push_back("-debug-info-kind=line-tables-only");
+ break;
+ case llvm::codegenoptions::DebugInfoConstructor:
+ CmdArgs.push_back("-debug-info-kind=constructor");
+ break;
+ case llvm::codegenoptions::LimitedDebugInfo:
+ CmdArgs.push_back("-debug-info-kind=limited");
+ break;
+ case llvm::codegenoptions::FullDebugInfo:
+ CmdArgs.push_back("-debug-info-kind=standalone");
+ break;
+ case llvm::codegenoptions::UnusedTypeInfo:
+ CmdArgs.push_back("-debug-info-kind=unused-types");
+ break;
+ default:
+ break;
+ }
+}
+
+// Convert an arg of the form "-gN" or "-ggdbN" or one of their aliases
+// to the corresponding DebugInfoKind.
+llvm::codegenoptions::DebugInfoKind tools::debugLevelToInfoKind(const Arg &A) {
+ assert(A.getOption().matches(options::OPT_gN_Group) &&
+ "Not a -g option that specifies a debug-info level");
+ if (A.getOption().matches(options::OPT_g0) ||
+ A.getOption().matches(options::OPT_ggdb0))
+ return llvm::codegenoptions::NoDebugInfo;
+ if (A.getOption().matches(options::OPT_gline_tables_only) ||
+ A.getOption().matches(options::OPT_ggdb1))
+ return llvm::codegenoptions::DebugLineTablesOnly;
+ if (A.getOption().matches(options::OPT_gline_directives_only))
+ return llvm::codegenoptions::DebugDirectivesOnly;
+ return llvm::codegenoptions::DebugInfoConstructor;
+}
+
+static unsigned ParseDebugDefaultVersion(const ToolChain &TC,
const ArgList &Args) {
const Arg *A = Args.getLastArg(options::OPT_fdebug_default_version);
@@ -1367,6 +2066,34 @@ unsigned tools::ParseDebugDefaultVersion(const ToolChain &TC,
return Value;
}
+unsigned tools::DwarfVersionNum(StringRef ArgValue) {
+ return llvm::StringSwitch<unsigned>(ArgValue)
+ .Case("-gdwarf-2", 2)
+ .Case("-gdwarf-3", 3)
+ .Case("-gdwarf-4", 4)
+ .Case("-gdwarf-5", 5)
+ .Default(0);
+}
+
+const Arg *tools::getDwarfNArg(const ArgList &Args) {
+ return Args.getLastArg(options::OPT_gdwarf_2, options::OPT_gdwarf_3,
+ options::OPT_gdwarf_4, options::OPT_gdwarf_5,
+ options::OPT_gdwarf);
+}
+
+unsigned tools::getDwarfVersion(const ToolChain &TC,
+ const llvm::opt::ArgList &Args) {
+ unsigned DwarfVersion = ParseDebugDefaultVersion(TC, Args);
+ if (const Arg *GDwarfN = getDwarfNArg(Args))
+ if (int N = DwarfVersionNum(GDwarfN->getSpelling()))
+ DwarfVersion = N;
+ if (DwarfVersion == 0) {
+ DwarfVersion = TC.GetDefaultDwarfVersion();
+ assert(DwarfVersion && "toolchain default DWARF version must be nonzero");
+ }
+ return DwarfVersion;
+}
+
void tools::AddAssemblerKPIC(const ToolChain &ToolChain, const ArgList &Args,
ArgStringList &CmdArgs) {
llvm::Reloc::Model RelocationModel;
@@ -1389,17 +2116,12 @@ enum class LibGccType { UnspecifiedLibGcc, StaticLibGcc, SharedLibGcc };
static LibGccType getLibGccType(const ToolChain &TC, const Driver &D,
const ArgList &Args) {
if (Args.hasArg(options::OPT_static_libgcc) ||
- Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_static_pie))
+ Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_static_pie) ||
+ // The Android NDK only provides libunwind.a, not libunwind.so.
+ TC.getTriple().isAndroid())
return LibGccType::StaticLibGcc;
if (Args.hasArg(options::OPT_shared_libgcc))
return LibGccType::SharedLibGcc;
- // The Android NDK only provides libunwind.a, not libunwind.so.
- if (TC.getTriple().isAndroid())
- return LibGccType::StaticLibGcc;
- // For MinGW, don't imply a shared libgcc here, we only want to return
- // SharedLibGcc if that was explicitly requested.
- if (D.CCCIsCXX() && !TC.getTriple().isOSCygMing())
- return LibGccType::SharedLibGcc;
return LibGccType::UnspecifiedLibGcc;
}
@@ -1419,18 +2141,25 @@ static LibGccType getLibGccType(const ToolChain &TC, const Driver &D,
static void AddUnwindLibrary(const ToolChain &TC, const Driver &D,
ArgStringList &CmdArgs, const ArgList &Args) {
ToolChain::UnwindLibType UNW = TC.GetUnwindLibType(Args);
+ // By default OHOS binaries are linked statically to libunwind.
+ if (TC.getTriple().isOHOSFamily() && UNW == ToolChain::UNW_CompilerRT) {
+ CmdArgs.push_back("-l:libunwind.a");
+ return;
+ }
+
// Targets that don't use unwind libraries.
if ((TC.getTriple().isAndroid() && UNW == ToolChain::UNW_Libgcc) ||
TC.getTriple().isOSIAMCU() || TC.getTriple().isOSBinFormatWasm() ||
- UNW == ToolChain::UNW_None)
+ TC.getTriple().isWindowsMSVCEnvironment() || UNW == ToolChain::UNW_None)
return;
LibGccType LGT = getLibGccType(TC, D, Args);
bool AsNeeded = LGT == LibGccType::UnspecifiedLibGcc &&
+ (UNW == ToolChain::UNW_CompilerRT || !D.CCCIsCXX()) &&
!TC.getTriple().isAndroid() &&
!TC.getTriple().isOSCygMing() && !TC.getTriple().isOSAIX();
if (AsNeeded)
- CmdArgs.push_back(getAsNeededOption(TC, true));
+ addAsNeededOption(TC, Args, CmdArgs, true);
switch (UNW) {
case ToolChain::UNW_None:
@@ -1450,30 +2179,32 @@ static void AddUnwindLibrary(const ToolChain &TC, const Driver &D,
CmdArgs.push_back("-lunwind");
} else if (LGT == LibGccType::StaticLibGcc) {
CmdArgs.push_back("-l:libunwind.a");
- } else if (TC.getTriple().isOSCygMing()) {
- if (LGT == LibGccType::SharedLibGcc)
+ } else if (LGT == LibGccType::SharedLibGcc) {
+ if (TC.getTriple().isOSCygMing())
CmdArgs.push_back("-l:libunwind.dll.a");
else
- // Let the linker choose between libunwind.dll.a and libunwind.a
- // depending on what's available, and depending on the -static flag
- CmdArgs.push_back("-lunwind");
+ CmdArgs.push_back("-l:libunwind.so");
} else {
- CmdArgs.push_back("-l:libunwind.so");
+ // Let the linker choose between libunwind.so and libunwind.a
+ // depending on what's available, and depending on the -static flag
+ CmdArgs.push_back("-lunwind");
}
break;
}
if (AsNeeded)
- CmdArgs.push_back(getAsNeededOption(TC, false));
+ addAsNeededOption(TC, Args, CmdArgs, false);
}
static void AddLibgcc(const ToolChain &TC, const Driver &D,
ArgStringList &CmdArgs, const ArgList &Args) {
LibGccType LGT = getLibGccType(TC, D, Args);
- if (LGT != LibGccType::SharedLibGcc)
+ if (LGT == LibGccType::StaticLibGcc ||
+ (LGT == LibGccType::UnspecifiedLibGcc && !D.CCCIsCXX()))
CmdArgs.push_back("-lgcc");
AddUnwindLibrary(TC, D, CmdArgs, Args);
- if (LGT == LibGccType::SharedLibGcc)
+ if (LGT == LibGccType::SharedLibGcc ||
+ (LGT == LibGccType::UnspecifiedLibGcc && D.CCCIsCXX()))
CmdArgs.push_back("-lgcc");
}
@@ -1492,9 +2223,10 @@ void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D,
if (TC.getTriple().isKnownWindowsMSVCEnvironment()) {
// Issue error diagnostic if libgcc is explicitly specified
// through command line as --rtlib option argument.
- if (Args.hasArg(options::OPT_rtlib_EQ)) {
+ Arg *A = Args.getLastArg(options::OPT_rtlib_EQ);
+ if (A && A->getValue() != StringRef("platform")) {
TC.getDriver().Diag(diag::err_drv_unsupported_rtlib_for_platform)
- << Args.getLastArg(options::OPT_rtlib_EQ)->getValue() << "MSVC";
+ << A->getValue() << "MSVC";
}
} else
AddLibgcc(TC, D, CmdArgs, Args);
@@ -1514,35 +2246,49 @@ SmallString<128> tools::getStatsFileName(const llvm::opt::ArgList &Args,
const InputInfo &Input,
const Driver &D) {
const Arg *A = Args.getLastArg(options::OPT_save_stats_EQ);
- if (!A)
+ if (!A && !D.CCPrintInternalStats)
return {};
- StringRef SaveStats = A->getValue();
SmallString<128> StatsFile;
- if (SaveStats == "obj" && Output.isFilename()) {
- StatsFile.assign(Output.getFilename());
- llvm::sys::path::remove_filename(StatsFile);
- } else if (SaveStats != "cwd") {
- D.Diag(diag::err_drv_invalid_value) << A->getAsString(Args) << SaveStats;
- return {};
- }
+ if (A) {
+ StringRef SaveStats = A->getValue();
+ if (SaveStats == "obj" && Output.isFilename()) {
+ StatsFile.assign(Output.getFilename());
+ llvm::sys::path::remove_filename(StatsFile);
+ } else if (SaveStats != "cwd") {
+ D.Diag(diag::err_drv_invalid_value) << A->getAsString(Args) << SaveStats;
+ return {};
+ }
- StringRef BaseName = llvm::sys::path::filename(Input.getBaseInput());
- llvm::sys::path::append(StatsFile, BaseName);
- llvm::sys::path::replace_extension(StatsFile, "stats");
+ StringRef BaseName = llvm::sys::path::filename(Input.getBaseInput());
+ llvm::sys::path::append(StatsFile, BaseName);
+ llvm::sys::path::replace_extension(StatsFile, "stats");
+ } else {
+ assert(D.CCPrintInternalStats);
+ StatsFile.assign(D.CCPrintInternalStatReportFilename.empty()
+ ? "-"
+ : D.CCPrintInternalStatReportFilename);
+ }
return StatsFile;
}
-void tools::addMultilibFlag(bool Enabled, const char *const Flag,
+void tools::addMultilibFlag(bool Enabled, const StringRef Flag,
Multilib::flags_list &Flags) {
- Flags.push_back(std::string(Enabled ? "+" : "-") + Flag);
+ assert(Flag.front() == '-');
+ if (Enabled) {
+ Flags.push_back(Flag.str());
+ } else {
+ Flags.push_back(("!" + Flag.substr(1)).str());
+ }
}
void tools::addX86AlignBranchArgs(const Driver &D, const ArgList &Args,
- ArgStringList &CmdArgs, bool IsLTO) {
+ ArgStringList &CmdArgs, bool IsLTO,
+ const StringRef PluginOptPrefix) {
auto addArg = [&, IsLTO](const Twine &Arg) {
if (IsLTO) {
- CmdArgs.push_back(Args.MakeArgString("-plugin-opt=" + Arg));
+ assert(!PluginOptPrefix.empty() && "Cannot have empty PluginOptPrefix!");
+ CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + Arg));
} else {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back(Args.MakeArgString(Arg));
@@ -1588,28 +2334,325 @@ 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.
+///
+static bool SDLSearch(const Driver &D, const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ const SmallVectorImpl<std::string> &LibraryPaths,
+ StringRef Lib, StringRef Arch, StringRef Target,
+ bool isBitCodeSDL) {
+ 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)) {
+ 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 tool.
+static void GetSDLFromOffloadArchive(
+ Compilation &C, const Driver &D, const Tool &T, const JobAction &JA,
+ const InputInfoList &Inputs, const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ const SmallVectorImpl<std::string> &LibraryPaths, StringRef Lib,
+ StringRef Arch, StringRef Target, bool isBitCodeSDL) {
+
+ // We don't support bitcode archive bundles for nvptx
+ if (isBitCodeSDL && Arch.contains("nvptx"))
+ return;
+
+ bool FoundAOB = false;
+ std::string ArchiveOfBundles;
+
+ llvm::Triple Triple(D.getTargetTriple());
+ bool IsMSVC = Triple.isWindowsMSVCEnvironment();
+ auto Ext = IsMSVC ? ".lib" : ".a";
+ if (!Lib.starts_with(":") && !Lib.starts_with("-l")) {
+ if (llvm::sys::fs::exists(Lib)) {
+ ArchiveOfBundles = Lib;
+ FoundAOB = true;
+ }
+ } else {
+ Lib.consume_front("-l");
+ for (auto LPath : LibraryPaths) {
+ ArchiveOfBundles.clear();
+ auto LibFile = (Lib.starts_with(":") ? Lib.drop_front()
+ : IsMSVC ? Lib + Ext
+ : "lib" + Lib + Ext)
+ .str();
+ for (auto Prefix : {"/libdevice/", "/"}) {
+ auto AOB = Twine(LPath + Prefix + LibFile).str();
+ if (llvm::sys::fs::exists(AOB)) {
+ ArchiveOfBundles = AOB;
+ FoundAOB = true;
+ break;
+ }
+ }
+ if (FoundAOB)
+ break;
+ }
+ }
+
+ if (!FoundAOB)
+ return;
+
+ llvm::file_magic Magic;
+ auto EC = llvm::identify_magic(ArchiveOfBundles, Magic);
+ if (EC || Magic != llvm::file_magic::archive)
+ return;
+
+ StringRef Prefix = isBitCodeSDL ? "libbc-" : "lib";
+ std::string OutputLib =
+ D.GetTemporaryPath(Twine(Prefix + llvm::sys::path::filename(Lib) + "-" +
+ Arch + "-" + Target)
+ .str(),
+ "a");
+
+ C.addTempFile(C.getArgs().MakeArgString(OutputLib));
+
+ 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("-input=" + ArchiveOfBundles);
+ std::string OffloadArg("-targets=" + std::string(DeviceTriple));
+ std::string OutputArg("-output=" + OutputLib);
+
+ const char *UBProgram = DriverArgs.MakeArgString(
+ T.getToolChain().GetProgramPath("clang-offload-bundler"));
+
+ ArgStringList UBArgs;
+ UBArgs.push_back(C.getArgs().MakeArgString(UnbundleArg));
+ UBArgs.push_back(C.getArgs().MakeArgString(TypeArg));
+ UBArgs.push_back(C.getArgs().MakeArgString(InputArg));
+ UBArgs.push_back(C.getArgs().MakeArgString(OffloadArg));
+ UBArgs.push_back(C.getArgs().MakeArgString(OutputArg));
+
+ // 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));
+
+ // Add this flag to treat hip and hipv4 offload kinds as compatible with
+ // openmp offload kind while extracting code objects from a heterogenous
+ // archive library. Vice versa is also considered compatible.
+ std::string HipCompatibleArgs("-hip-openmp-compatible");
+ UBArgs.push_back(C.getArgs().MakeArgString(HipCompatibleArgs));
+
+ C.addCommand(std::make_unique<Command>(
+ JA, T, ResponseFileSupport::AtFileCurCP(), UBProgram, UBArgs, Inputs,
+ InputInfo(&JA, C.getArgs().MakeArgString(OutputLib))));
+
+ CC1Args.push_back(DriverArgs.MakeArgString(OutputLib));
+
+ return;
+}
+
+// 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) {
+ AddStaticDeviceLibs(&C, &T, &JA, &Inputs, C.getDriver(), DriverArgs, CC1Args,
+ Arch, Target, isBitCodeSDL);
+}
+
+// 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 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) {
+
+ SmallVector<std::string, 8> LibraryPaths;
+ // Add search directories from LIBRARY_PATH env variable
+ std::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, CLANG_INSTALL_LIBDIR_BASENAME);
+ 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 (!llvm::is_contained(HostOnlyArchives, SDLName)) {
+ SDLNames.insert(std::string("-l") + SDLName);
+ }
+ }
+
+ for (auto Input : DriverArgs.getAllArgValues(options::OPT_INPUT)) {
+ auto FileName = StringRef(Input);
+ // Clang treats any unknown file types as archives and passes them to the
+ // linker. Files with extension 'lib' are classified as TY_Object by clang
+ // but they are usually archives. It is OK if the file is not really an
+ // archive since GetSDLFromOffloadArchive will check the magic of the file
+ // and only unbundle it if it is really an archive.
+ const StringRef LibFileExt = ".lib";
+ if (!llvm::sys::path::has_extension(FileName) ||
+ types::lookupTypeForExtension(
+ llvm::sys::path::extension(FileName).drop_front()) ==
+ types::TY_INVALID ||
+ llvm::sys::path::extension(FileName) == LibFileExt)
+ SDLNames.insert(Input);
+ }
+
+ // 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 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)) {
+ GetSDLFromOffloadArchive(*C, D, *T, *JA, *Inputs, DriverArgs, CC1Args,
+ LibraryPaths, SDLName, Arch, Target,
+ isBitCodeSDL);
+ }
+ }
+}
+
static llvm::opt::Arg *
getAMDGPUCodeObjectArgument(const Driver &D, const llvm::opt::ArgList &Args) {
- // The last of -mcode-object-v3, -mno-code-object-v3 and
- // -mcode-object-version=<version> wins.
- return Args.getLastArg(options::OPT_mcode_object_v3_legacy,
- options::OPT_mno_code_object_v3_legacy,
- options::OPT_mcode_object_version_EQ);
+ return Args.getLastArg(options::OPT_mcode_object_version_EQ);
}
void tools::checkAMDGPUCodeObjectVersion(const Driver &D,
const llvm::opt::ArgList &Args) {
- const unsigned MinCodeObjVer = 2;
- const unsigned MaxCodeObjVer = 4;
-
- // Emit warnings for legacy options even if they are overridden.
- if (Args.hasArg(options::OPT_mno_code_object_v3_legacy))
- D.Diag(diag::warn_drv_deprecated_arg) << "-mno-code-object-v3"
- << "-mcode-object-version=2";
-
- if (Args.hasArg(options::OPT_mcode_object_v3_legacy))
- D.Diag(diag::warn_drv_deprecated_arg) << "-mcode-object-v3"
- << "-mcode-object-version=3";
+ const unsigned MinCodeObjVer = 4;
+ const unsigned MaxCodeObjVer = 5;
if (auto *CodeObjArg = getAMDGPUCodeObjectArgument(D, Args)) {
if (CodeObjArg->getOption().getID() ==
@@ -1627,17 +2670,8 @@ void tools::checkAMDGPUCodeObjectVersion(const Driver &D,
unsigned tools::getAMDGPUCodeObjectVersion(const Driver &D,
const llvm::opt::ArgList &Args) {
unsigned CodeObjVer = 4; // default
- if (auto *CodeObjArg = getAMDGPUCodeObjectArgument(D, Args)) {
- if (CodeObjArg->getOption().getID() ==
- options::OPT_mno_code_object_v3_legacy) {
- CodeObjVer = 2;
- } else if (CodeObjArg->getOption().getID() ==
- options::OPT_mcode_object_v3_legacy) {
- CodeObjVer = 3;
- } else {
- StringRef(CodeObjArg->getValue()).getAsInteger(0, CodeObjVer);
- }
- }
+ if (auto *CodeObjArg = getAMDGPUCodeObjectArgument(D, Args))
+ StringRef(CodeObjArg->getValue()).getAsInteger(0, CodeObjVer);
return CodeObjVer;
}
@@ -1649,10 +2683,12 @@ bool tools::haveAMDGPUCodeObjectVersionArgument(
void tools::addMachineOutlinerArgs(const Driver &D,
const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
- const llvm::Triple &Triple, bool IsLTO) {
+ const llvm::Triple &Triple, bool IsLTO,
+ const StringRef PluginOptPrefix) {
auto addArg = [&, IsLTO](const Twine &Arg) {
if (IsLTO) {
- CmdArgs.push_back(Args.MakeArgString("-plugin-opt=" + Arg));
+ assert(!PluginOptPrefix.empty() && "Cannot have empty PluginOptPrefix!");
+ CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + Arg));
} else {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back(Args.MakeArgString(Arg));
@@ -1665,9 +2701,7 @@ void tools::addMachineOutlinerArgs(const Driver &D,
// We only support -moutline in AArch64 and ARM targets right now. If
// we're not compiling for these, emit a warning and ignore the flag.
// Otherwise, add the proper mllvm flags.
- if (!(Triple.isARM() || Triple.isThumb() ||
- Triple.getArch() == llvm::Triple::aarch64 ||
- Triple.getArch() == llvm::Triple::aarch64_32)) {
+ if (!(Triple.isARM() || Triple.isThumb() || Triple.isAArch64())) {
D.Diag(diag::warn_drv_moutline_unsupported_opt) << Triple.getArchName();
} else {
addArg(Twine("-enable-machine-outliner"));
@@ -1685,8 +2719,14 @@ 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, CLANG_INSTALL_LIBDIR_BASENAME);
+ LibraryPaths.emplace_back(DefaultLibPath.c_str());
+
// Add user defined library paths from LIBRARY_PATH.
- llvm::Optional<std::string> LibPath =
+ std::optional<std::string> LibPath =
llvm::sys::Process::GetEnv("LIBRARY_PATH");
if (LibPath) {
SmallVector<StringRef, 8> Frags;
@@ -1696,32 +2736,32 @@ 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
+ Triple.isAMDGCN() ? options::OPT_libomptarget_amdgpu_bc_path_EQ
: options::OPT_libomptarget_nvptx_bc_path_EQ;
- StringRef ArchPrefix = Triple.isAMDGCN() ? "amdgcn" : "nvptx";
+ StringRef ArchPrefix = Triple.isAMDGCN() ? "amdgpu" : "nvptx";
+ std::string LibOmpTargetName =
+ ("libomptarget-" + ArchPrefix + "-" + BitcodeSuffix + ".bc").str();
+
// First check whether user specifies bc library
if (const Arg *A = DriverArgs.getLastArg(LibomptargetBCPathOpt)) {
- 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);
@@ -1738,3 +2778,17 @@ void tools::addOpenMPDeviceRTL(const Driver &D,
<< LibOmpTargetName << ArchPrefix;
}
}
+void tools::addHIPRuntimeLibArgs(const ToolChain &TC, Compilation &C,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) {
+ if ((C.getActiveOffloadKinds() & Action::OFK_HIP) &&
+ !Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_no_hip_rt)) {
+ TC.AddHIPRuntimeLibArgs(Args, CmdArgs);
+ } else {
+ // Claim "no HIP libraries" arguments if any
+ for (auto *Arg : Args.filtered(options::OPT_no_hip_rt)) {
+ Arg->claim();
+ }
+ }
+}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.h
index c94c15864661..807867f13a5c 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/CommonArgs.h
@@ -9,11 +9,15 @@
#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_COMMONARGS_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_COMMONARGS_H
+#include "clang/Basic/CodeGenOptions.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Multilib.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
#include "llvm/Support/CodeGen.h"
namespace clang {
@@ -37,18 +41,32 @@ bool addSanitizerRuntimes(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);
void linkSanitizerRuntimeDeps(const ToolChain &TC,
+ const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);
bool addXRayRuntime(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);
-void linkXRayRuntimeDeps(const ToolChain &TC,
+void linkXRayRuntimeDeps(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);
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);
+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);
+
const char *SplitDebugName(const JobAction &JA, const llvm::opt::ArgList &Args,
const InputInfo &Input, const InputInfo &Output);
@@ -60,14 +78,28 @@ void addLTOOptions(const ToolChain &ToolChain, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs, const InputInfo &Output,
const InputInfo &Input, bool IsThinLTO);
+const char *RelocationModelName(llvm::Reloc::Model Model);
+
std::tuple<llvm::Reloc::Model, unsigned, bool>
ParsePICArgs(const ToolChain &ToolChain, const llvm::opt::ArgList &Args);
unsigned ParseFunctionAlignment(const ToolChain &TC,
const llvm::opt::ArgList &Args);
-unsigned ParseDebugDefaultVersion(const ToolChain &TC,
- const llvm::opt::ArgList &Args);
+void addDebugInfoKind(llvm::opt::ArgStringList &CmdArgs,
+ llvm::codegenoptions::DebugInfoKind DebugInfoKind);
+
+llvm::codegenoptions::DebugInfoKind
+debugLevelToInfoKind(const llvm::opt::Arg &A);
+
+// Extract the integer N from a string spelled "-dwarf-N", returning 0
+// on mismatch. The StringRef input (rather than an Arg) allows
+// for use by the "-Xassembler" option parser.
+unsigned DwarfVersionNum(StringRef ArgValue);
+// Find a DWARF format version option.
+// This function is a complementary for DwarfVersionNum().
+const llvm::opt::Arg *getDwarfNArg(const llvm::opt::ArgList &Args);
+unsigned getDwarfVersion(const ToolChain &TC, const llvm::opt::ArgList &Args);
void AddAssemblerKPIC(const ToolChain &ToolChain,
const llvm::opt::ArgList &Args,
@@ -75,12 +107,32 @@ void AddAssemblerKPIC(const ToolChain &ToolChain,
void addArchSpecificRPath(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);
+void addOpenMPRuntimeLibraryPath(const ToolChain &TC,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs);
/// Returns true, if an OpenMP runtime has been added.
bool addOpenMPRuntime(llvm::opt::ArgStringList &CmdArgs, const ToolChain &TC,
const llvm::opt::ArgList &Args,
bool ForceStaticHostRuntime = false,
bool IsOffloadingHost = false, bool GompNeedsRT = false);
+/// Adds Fortran runtime libraries to \p CmdArgs.
+void addFortranRuntimeLibs(const ToolChain &TC, const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs);
+
+/// Adds the path for the Fortran runtime libraries to \p CmdArgs.
+void addFortranRuntimeLibraryPath(const ToolChain &TC,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs);
+
+void addHIPRuntimeLibArgs(const ToolChain &TC, Compilation &C,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs);
+
+void addAsNeededOption(const ToolChain &TC, const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs, bool as_needed);
+
+llvm::opt::Arg *getLastCSProfileGenerateArg(const llvm::opt::ArgList &Args);
llvm::opt::Arg *getLastProfileUseArg(const llvm::opt::ArgList &Args);
llvm::opt::Arg *getLastProfileSampleUseArg(const llvm::opt::ArgList &Args);
@@ -92,6 +144,9 @@ llvm::StringRef getLTOParallelism(const llvm::opt::ArgList &Args,
bool areOptimizationsEnabled(const llvm::opt::ArgList &Args);
bool isUseSeparateSections(const llvm::Triple &Triple);
+// Parse -mtls-dialect=. Return true if the target supports both general-dynamic
+// and TLSDESC, and TLSDESC is requested.
+bool isTLSDESCEnabled(const ToolChain &TC, const llvm::opt::ArgList &Args);
/// \p EnvVar is split by system delimiter for environment variables.
/// If \p ArgName is "-I", "-L", or an empty string, each entry from \p EnvVar
@@ -107,8 +162,13 @@ 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);
+
+void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs, bool ForAS,
+ bool IsAux = false);
/// Iterate \p Args and convert -mxxx to +xxx and -mno-xxx to -xxx and
/// append it to \p Features.
@@ -116,13 +176,13 @@ std::string getCPUName(const llvm::opt::ArgList &Args, const llvm::Triple &T,
/// Note: Since \p Features may contain default values before calling
/// this function, or may be appended with entries to override arguments,
/// entries in \p Features are not unique.
-void handleTargetFeaturesGroup(const llvm::opt::ArgList &Args,
+void handleTargetFeaturesGroup(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args,
std::vector<StringRef> &Features,
llvm::opt::OptSpecifier Group);
/// If there are multiple +xxx or -xxx features, keep the last one.
-std::vector<StringRef>
-unifyTargetFeatures(const std::vector<StringRef> &Features);
+SmallVector<StringRef> unifyTargetFeatures(ArrayRef<StringRef> Features);
/// Handles the -save-stats option and returns the filename to save statistics
/// to.
@@ -130,13 +190,13 @@ SmallString<128> getStatsFileName(const llvm::opt::ArgList &Args,
const InputInfo &Output,
const InputInfo &Input, const Driver &D);
-/// \p Flag must be a flag accepted by the driver with its leading '-' removed,
-// otherwise '-print-multi-lib' will not emit them correctly.
-void addMultilibFlag(bool Enabled, const char *const Flag,
+/// \p Flag must be a flag accepted by the driver.
+void addMultilibFlag(bool Enabled, const StringRef Flag,
Multilib::flags_list &Flags);
void addX86AlignBranchArgs(const Driver &D, const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs, bool IsLTO);
+ llvm::opt::ArgStringList &CmdArgs, bool IsLTO,
+ const StringRef PluginOptPrefix = "");
void checkAMDGPUCodeObjectVersion(const Driver &D,
const llvm::opt::ArgList &Args);
@@ -149,7 +209,8 @@ bool haveAMDGPUCodeObjectVersionArgument(const Driver &D,
void addMachineOutlinerArgs(const Driver &D, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
- const llvm::Triple &Triple, bool IsLTO);
+ const llvm::Triple &Triple, bool IsLTO,
+ const StringRef PluginOptPrefix = "");
void addOpenMPDeviceRTL(const Driver &D, const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
@@ -158,4 +219,7 @@ void addOpenMPDeviceRTL(const Driver &D, const llvm::opt::ArgList &DriverArgs,
} // end namespace driver
} // end namespace clang
+clang::CodeGenOptions::FramePointerKind
+getFramePointerKind(const llvm::opt::ArgList &Args, const llvm::Triple &Triple);
+
#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_COMMONARGS_H
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Contiki.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Contiki.cpp
deleted file mode 100644
index 5dda1b1b09fb..000000000000
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Contiki.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-//===--- Contiki.cpp - Contiki ToolChain Implementations --------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "Contiki.h"
-#include "CommonArgs.h"
-
-using namespace clang::driver;
-using namespace clang::driver::toolchains;
-using namespace clang;
-using namespace llvm::opt;
-
-Contiki::Contiki(const Driver &D, const llvm::Triple &Triple,
- const ArgList &Args)
- : Generic_ELF(D, Triple, Args) {}
-
-SanitizerMask Contiki::getSupportedSanitizers() const {
- const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
- SanitizerMask Res = ToolChain::getSupportedSanitizers();
- if (IsX86)
- Res |= SanitizerKind::SafeStack;
- return Res;
-}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Contiki.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Contiki.h
deleted file mode 100644
index 627d80bdda09..000000000000
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Contiki.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//===--- Contiki.h - Contiki ToolChain Implementations ----------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CONTIKI_H
-#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CONTIKI_H
-
-#include "Gnu.h"
-#include "clang/Driver/ToolChain.h"
-
-namespace clang {
-namespace driver {
-namespace toolchains {
-
-class LLVM_LIBRARY_VISIBILITY Contiki : public Generic_ELF {
-public:
- Contiki(const Driver &D, const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args);
-
- // No support for finding a C++ standard library yet.
- void addLibCxxIncludePaths(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override {}
- void addLibStdCxxIncludePaths(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override {}
-
- SanitizerMask getSupportedSanitizers() const override;
-};
-
-} // end namespace toolchains
-} // end namespace driver
-} // end namespace clang
-
-#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CONTIKI_H
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/CrossWindows.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/CrossWindows.cpp
index 07abf4f83f7d..3c5dfba329cf 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/CrossWindows.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/CrossWindows.cpp
@@ -94,7 +94,8 @@ void tools::CrossWindows::Linker::ConstructJob(
CmdArgs.push_back("-m");
switch (TC.getArch()) {
default:
- llvm_unreachable("unsupported architecture");
+ D.Diag(diag::err_target_unknown_triple) << TC.getEffectiveTriple().str();
+ break;
case llvm::Triple::arm:
case llvm::Triple::thumb:
// FIXME: this is incorrect for WinCE
@@ -185,7 +186,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"));
@@ -213,17 +214,18 @@ CrossWindowsToolChain::CrossWindowsToolChain(const Driver &D,
const llvm::opt::ArgList &Args)
: Generic_GCC(D, T, Args) {}
-bool CrossWindowsToolChain::IsUnwindTablesDefault(const ArgList &Args) const {
+ToolChain::UnwindTableLevel
+CrossWindowsToolChain::getDefaultUnwindTableLevel(const ArgList &Args) const {
// FIXME: all non-x86 targets need unwind tables, however, LLVM currently does
// not know how to emit them.
- return getArch() == llvm::Triple::x86_64;
+ return getArch() == llvm::Triple::x86_64 ? UnwindTableLevel::Asynchronous : UnwindTableLevel::None;
}
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;
}
@@ -273,8 +275,11 @@ AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
void CrossWindowsToolChain::
AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const {
- if (GetCXXStdlibType(Args) == ToolChain::CST_Libcxx)
+ if (GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) {
CmdArgs.push_back("-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
+ }
}
clang::SanitizerMask CrossWindowsToolChain::getSupportedSanitizers() const {
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/CrossWindows.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/CrossWindows.h
index ffe75332c2e8..c5df55a24296 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/CrossWindows.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/CrossWindows.h
@@ -20,7 +20,7 @@ namespace driver {
namespace tools {
namespace CrossWindows {
-class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
+class LLVM_LIBRARY_VISIBILITY Assembler final : public Tool {
public:
Assembler(const ToolChain &TC) : Tool("CrossWindows::Assembler", "as", TC) {}
@@ -32,7 +32,7 @@ public:
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
public:
Linker(const ToolChain &TC) : Tool("CrossWindows::Linker", "ld", TC) {}
@@ -54,10 +54,10 @@ public:
CrossWindowsToolChain(const Driver &D, const llvm::Triple &T,
const llvm::opt::ArgList &Args);
- bool IsIntegratedAssemblerDefault() const override { return true; }
- bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override;
+ UnwindTableLevel
+ getDefaultUnwindTableLevel(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/contrib/llvm-project/clang/lib/Driver/ToolChains/Cuda.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Cuda.cpp
index 769eae14df51..1462576ca870 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Cuda.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Cuda.cpp
@@ -16,15 +16,17 @@
#include "clang/Driver/DriverDiagnostic.h"
#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"
+#include "llvm/Support/FormatAdapters.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
-#include "llvm/Support/TargetParser.h"
#include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/TargetParser/Host.h"
+#include "llvm/TargetParser/TargetParser.h"
#include <system_error>
using namespace clang::driver;
@@ -34,25 +36,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,15 +60,37 @@ 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;
+ if (raw_version < 11070)
+ return CudaVersion::CUDA_116;
+ if (raw_version < 11080)
+ return CudaVersion::CUDA_117;
+ if (raw_version < 11090)
+ return CudaVersion::CUDA_118;
+ if (raw_version < 12010)
+ return CudaVersion::CUDA_120;
+ if (raw_version < 12020)
+ return CudaVersion::CUDA_121;
+ if (raw_version < 12030)
+ return CudaVersion::CUDA_122;
+ if (raw_version < 12040)
+ return CudaVersion::CUDA_123;
+ 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.
+ // std::nullopt otherwise.
auto StartsWithWords =
[](llvm::StringRef Line,
- const SmallVector<StringRef, 3> words) -> llvm::Optional<StringRef> {
+ const SmallVector<StringRef, 3> words) -> std::optional<StringRef> {
for (StringRef word : words) {
if (!Line.consume_front(word))
return {};
@@ -100,21 +105,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(
@@ -193,44 +204,17 @@ CudaInstallationDetector::CudaInstallationDetector(
if (CheckLibDevice && !FS.exists(LibDevicePath))
continue;
- // On Linux, we have both lib and lib64 directories, and we need to choose
- // based on our triple. On MacOS, we have only a lib directory.
- //
- // It's sufficient for our purposes to be flexible: If both lib and lib64
- // exist, we choose whichever one matches our triple. Otherwise, if only
- // lib exists, we use it.
- if (HostTriple.isArch64Bit() && FS.exists(InstallPath + "/lib64"))
- LibPath = InstallPath + "/lib64";
- else if (FS.exists(InstallPath + "/lib"))
- LibPath = InstallPath + "/lib";
- 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";
@@ -254,7 +238,7 @@ CudaInstallationDetector::CudaInstallationDetector(
// Process all bitcode filenames that look like
// libdevice.compute_XX.YY.bc
const StringRef LibDeviceName = "libdevice.";
- if (!(FileName.startswith(LibDeviceName) && FileName.endswith(".bc")))
+ if (!(FileName.starts_with(LibDeviceName) && FileName.ends_with(".bc")))
continue;
StringRef GpuArch = FileName.slice(
LibDeviceName.size(), FileName.find('.', LibDeviceName.size()));
@@ -319,8 +303,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");
}
@@ -395,18 +377,20 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const ArgList &Args,
const char *LinkingOutput) const {
const auto &TC =
- static_cast<const toolchains::CudaToolChain &>(getToolChain());
+ static_cast<const toolchains::NVPTXToolChain &>(getToolChain());
assert(TC.getTriple().isNVPTX() && "Wrong platform");
StringRef GPUArchName;
- // If this is an OpenMP action we need to extract the device architecture
- // from the -march=arch option. This option may come from -Xopenmp-target
- // flag or the default value.
- if (JA.isDeviceOffloading(Action::OFK_OpenMP)) {
+ // If this is a CUDA action we need to extract the device architecture
+ // from the Job's associated architecture, otherwise use the -march=arch
+ // option. This option may come from -Xopenmp-target flag or the default
+ // value.
+ if (JA.isDeviceOffloading(Action::OFK_Cuda)) {
+ GPUArchName = JA.getOffloadingArch();
+ } else {
GPUArchName = Args.getLastArgValue(options::OPT_march_EQ);
assert(!GPUArchName.empty() && "Must have an architecture passed in.");
- } else
- GPUArchName = JA.getOffloadingArch();
+ }
// Obtain architecture from the action.
CudaArch gpu_arch = StringToCudaArch(GPUArchName);
@@ -467,22 +451,38 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("--gpu-name");
CmdArgs.push_back(Args.MakeArgString(CudaArchToString(gpu_arch)));
CmdArgs.push_back("--output-file");
- CmdArgs.push_back(Args.MakeArgString(TC.getInputFilename(Output)));
- for (const auto& II : Inputs)
+ std::string OutputFileName = TC.getInputFilename(Output);
+
+ // If we are invoking `nvlink` internally we need to output a `.cubin` file.
+ // FIXME: This should hopefully be removed if NVIDIA updates their tooling.
+ if (!C.getInputArgs().getLastArg(options::OPT_c)) {
+ SmallString<256> Filename(Output.getFilename());
+ llvm::sys::path::replace_extension(Filename, "cubin");
+ OutputFileName = Filename.str();
+ }
+ if (Output.isFilename() && OutputFileName != Output.getFilename())
+ C.addTempFile(Args.MakeArgString(OutputFileName));
+
+ CmdArgs.push_back(Args.MakeArgString(OutputFileName));
+ for (const auto &II : Inputs)
CmdArgs.push_back(Args.MakeArgString(II.getFilename()));
- for (const auto& A : Args.getAllArgValues(options::OPT_Xcuda_ptxas))
+ for (const auto &A : Args.getAllArgValues(options::OPT_Xcuda_ptxas))
CmdArgs.push_back(Args.MakeArgString(A));
- bool Relocatable = false;
+ bool Relocatable;
if (JA.isOffloading(Action::OFK_OpenMP))
// In OpenMP we need to generate relocatable code.
Relocatable = Args.hasFlag(options::OPT_fopenmp_relocatable_target,
options::OPT_fnoopenmp_relocatable_target,
/*Default=*/true);
else if (JA.isOffloading(Action::OFK_Cuda))
- Relocatable = Args.hasFlag(options::OPT_fgpu_rdc,
- options::OPT_fno_gpu_rdc, /*Default=*/false);
+ // In CUDA we generate relocatable code by default.
+ Relocatable = Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
+ /*Default=*/false);
+ else
+ // Otherwise, we are compiling directly and should create linkable output.
+ Relocatable = true;
if (Relocatable)
CmdArgs.push_back("-c");
@@ -518,11 +518,11 @@ static bool shouldIncludePTX(const ArgList &Args, const char *gpu_arch) {
// All inputs to this linker must be from CudaDeviceActions, as we need to look
// at the Inputs' Actions in order to figure out which GPU architecture they
// correspond to.
-void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void NVPTX::FatBinary::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
const auto &TC =
static_cast<const toolchains::CudaToolChain &>(getToolChain());
assert(TC.getTriple().isNVPTX() && "Wrong platform");
@@ -536,7 +536,7 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (mustEmitDebugInfo(Args) == EmitSameDebugInfoAsHost)
CmdArgs.push_back("-g");
- for (const auto& II : Inputs) {
+ for (const auto &II : Inputs) {
auto *A = II.getAction();
assert(A->getInputs().size() == 1 &&
"Device offload action is expected to have a single input");
@@ -553,11 +553,12 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const char *Arch = (II.getType() == types::TY_PP_Asm)
? CudaArchToVirtualArchString(gpu_arch)
: gpu_arch_str;
- CmdArgs.push_back(Args.MakeArgString(llvm::Twine("--image=profile=") +
- Arch + ",file=" + II.getFilename()));
+ CmdArgs.push_back(
+ Args.MakeArgString(llvm::Twine("--image=profile=") + Arch +
+ ",file=" + getToolChain().getInputFilename(II)));
}
- for (const auto& A : Args.getAllArgValues(options::OPT_Xcuda_fatbinary))
+ for (const auto &A : Args.getAllArgValues(options::OPT_Xcuda_fatbinary))
CmdArgs.push_back(Args.MakeArgString(A));
const char *Exec = Args.MakeArgString(TC.GetProgramPath("fatbinary"));
@@ -568,36 +569,31 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Exec, CmdArgs, Inputs, Output));
}
-void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
const auto &TC =
- static_cast<const toolchains::CudaToolChain &>(getToolChain());
- assert(TC.getTriple().isNVPTX() && "Wrong platform");
-
+ static_cast<const toolchains::NVPTXToolChain &>(getToolChain());
ArgStringList CmdArgs;
- // OpenMP uses nvlink to link cubin files. The result will be embedded in the
- // host binary by the host linker.
- assert(!JA.isHostOffloading(Action::OFK_OpenMP) &&
- "CUDA toolchain not expected for an OpenMP host device.");
+ assert(TC.getTriple().isNVPTX() && "Wrong platform");
+ assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- } else
- assert(Output.isNothing() && "Invalid output.");
+ }
+
if (mustEmitDebugInfo(Args) == EmitSameDebugInfoAsHost)
CmdArgs.push_back("-g");
if (Args.hasArg(options::OPT_v))
CmdArgs.push_back("-v");
- StringRef GPUArch =
- Args.getLastArgValue(options::OPT_march_EQ);
- assert(!GPUArch.empty() && "At least one GPU Arch required for ptxas.");
+ StringRef GPUArch = Args.getLastArgValue(options::OPT_march_EQ);
+ assert(!GPUArch.empty() && "At least one GPU Arch required for nvlink.");
CmdArgs.push_back("-arch");
CmdArgs.push_back(Args.MakeArgString(GPUArch));
@@ -608,14 +604,12 @@ void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA,
// Add paths for the default clang library path.
SmallString<256> DefaultLibPath =
llvm::sys::path::parent_path(TC.getDriver().Dir);
- llvm::sys::path::append(DefaultLibPath, "lib" CLANG_LIBDIR_SUFFIX);
+ llvm::sys::path::append(DefaultLibPath, CLANG_INSTALL_LIBDIR_BASENAME);
CmdArgs.push_back(Args.MakeArgString(Twine("-L") + DefaultLibPath));
for (const auto &II : Inputs) {
- if (II.getType() == types::TY_LLVM_IR ||
- II.getType() == types::TY_LTO_IR ||
- II.getType() == types::TY_LTO_BC ||
- II.getType() == types::TY_LLVM_BC) {
+ if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR ||
+ II.getType() == types::TY_LTO_BC || II.getType() == types::TY_LLVM_BC) {
C.getDriver().Diag(diag::err_drv_no_linker_llvm_support)
<< getToolChain().getTripleString();
continue;
@@ -626,56 +620,179 @@ void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA,
if (!II.isFilename())
continue;
- const char *CubinF = C.addTempFile(
- C.getArgs().MakeArgString(getToolChain().getInputFilename(II)));
+ // The 'nvlink' application performs RDC-mode linking when given a '.o'
+ // file and device linking when given a '.cubin' file. We always want to
+ // perform device linking, so just rename any '.o' files.
+ // FIXME: This should hopefully be removed if NVIDIA updates their tooling.
+ auto InputFile = getToolChain().getInputFilename(II);
+ if (llvm::sys::path::extension(InputFile) != ".cubin") {
+ // If there are no actions above this one then this is direct input and we
+ // can copy it. Otherwise the input is internal so a `.cubin` file should
+ // exist.
+ if (II.getAction() && II.getAction()->getInputs().size() == 0) {
+ const char *CubinF =
+ Args.MakeArgString(getToolChain().getDriver().GetTemporaryPath(
+ llvm::sys::path::stem(InputFile), "cubin"));
+ if (llvm::sys::fs::copy_file(InputFile, C.addTempFile(CubinF)))
+ continue;
- CmdArgs.push_back(CubinF);
+ CmdArgs.push_back(CubinF);
+ } else {
+ SmallString<256> Filename(InputFile);
+ llvm::sys::path::replace_extension(Filename, "cubin");
+ CmdArgs.push_back(Args.MakeArgString(Filename));
+ }
+ } else {
+ CmdArgs.push_back(Args.MakeArgString(InputFile));
+ }
}
- const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("nvlink"));
C.addCommand(std::make_unique<Command>(
JA, *this,
ResponseFileSupport{ResponseFileSupport::RF_Full, llvm::sys::WEM_UTF8,
"--options-file"},
- Exec, CmdArgs, Inputs, Output));
+ Args.MakeArgString(getToolChain().GetProgramPath("nvlink")), CmdArgs,
+ Inputs, Output));
}
-/// CUDA toolchain. Our assembler is ptxas, and our "linker" is fatbinary,
-/// which isn't properly a linker but nonetheless performs the step of stitching
-/// together object files from the assembler into a single blob.
+void NVPTX::getNVPTXTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args,
+ std::vector<StringRef> &Features) {
+ if (Args.hasArg(options::OPT_cuda_feature_EQ)) {
+ StringRef PtxFeature =
+ Args.getLastArgValue(options::OPT_cuda_feature_EQ, "+ptx42");
+ Features.push_back(Args.MakeArgString(PtxFeature));
+ return;
+ }
+ CudaInstallationDetector CudaInstallation(D, Triple, Args);
-CudaToolChain::CudaToolChain(const Driver &D, const llvm::Triple &Triple,
- const ToolChain &HostTC, const ArgList &Args,
- const Action::OffloadKind OK)
- : ToolChain(D, Triple, Args), HostTC(HostTC),
- CudaInstallation(D, HostTC.getTriple(), Args), OK(OK) {
- if (CudaInstallation.isValid()) {
- CudaInstallation.WarnIfUnsupportedVersion();
- getProgramPaths().push_back(std::string(CudaInstallation.getBinPath()));
+ // New CUDA versions often introduce new instructions that are only supported
+ // by new PTX version, so we need to raise PTX level to enable them in NVPTX
+ // back-end.
+ const char *PtxFeature = nullptr;
+ switch (CudaInstallation.version()) {
+#define CASE_CUDA_VERSION(CUDA_VER, PTX_VER) \
+ case CudaVersion::CUDA_##CUDA_VER: \
+ PtxFeature = "+ptx" #PTX_VER; \
+ break;
+ CASE_CUDA_VERSION(123, 83);
+ CASE_CUDA_VERSION(122, 82);
+ CASE_CUDA_VERSION(121, 81);
+ CASE_CUDA_VERSION(120, 80);
+ CASE_CUDA_VERSION(118, 78);
+ CASE_CUDA_VERSION(117, 77);
+ CASE_CUDA_VERSION(116, 76);
+ CASE_CUDA_VERSION(115, 75);
+ CASE_CUDA_VERSION(114, 74);
+ CASE_CUDA_VERSION(113, 73);
+ CASE_CUDA_VERSION(112, 72);
+ CASE_CUDA_VERSION(111, 71);
+ CASE_CUDA_VERSION(110, 70);
+ CASE_CUDA_VERSION(102, 65);
+ CASE_CUDA_VERSION(101, 64);
+ CASE_CUDA_VERSION(100, 63);
+ CASE_CUDA_VERSION(92, 61);
+ CASE_CUDA_VERSION(91, 61);
+ CASE_CUDA_VERSION(90, 60);
+#undef CASE_CUDA_VERSION
+ default:
+ PtxFeature = "+ptx42";
}
+ Features.push_back(PtxFeature);
+}
+
+/// NVPTX toolchain. Our assembler is ptxas, and our linker is nvlink. This
+/// operates as a stand-alone version of the NVPTX tools without the host
+/// toolchain.
+NVPTXToolChain::NVPTXToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::Triple &HostTriple,
+ const ArgList &Args, bool Freestanding = false)
+ : ToolChain(D, Triple, Args), CudaInstallation(D, HostTriple, Args),
+ Freestanding(Freestanding) {
+ if (CudaInstallation.isValid())
+ getProgramPaths().push_back(std::string(CudaInstallation.getBinPath()));
// Lookup binaries into the driver directory, this is used to
- // discover the clang-offload-bundler executable.
+ // discover the 'nvptx-arch' executable.
getProgramPaths().push_back(getDriver().Dir);
}
-std::string CudaToolChain::getInputFilename(const InputInfo &Input) const {
- // Only object files are changed, for example assembly files keep their .s
- // extensions. CUDA also continues to use .o as they don't use nvlink but
- // fatbinary.
- if (!(OK == Action::OFK_OpenMP && Input.getType() == types::TY_Object))
- return ToolChain::getInputFilename(Input);
+/// We only need the host triple to locate the CUDA binary utilities, use the
+/// system's default triple if not provided.
+NVPTXToolChain::NVPTXToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : NVPTXToolChain(D, Triple, llvm::Triple(LLVM_HOST_TRIPLE), Args,
+ /*Freestanding=*/true) {}
- // Replace extension for object files with cubin because nvlink relies on
- // these particular file names.
- SmallString<256> Filename(ToolChain::getInputFilename(Input));
- llvm::sys::path::replace_extension(Filename, "cubin");
- return std::string(Filename.str());
+llvm::opt::DerivedArgList *
+NVPTXToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
+ StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind) const {
+ DerivedArgList *DAL =
+ ToolChain::TranslateArgs(Args, BoundArch, DeviceOffloadKind);
+ if (!DAL)
+ DAL = new DerivedArgList(Args.getBaseArgs());
+
+ const OptTable &Opts = getDriver().getOpts();
+
+ for (Arg *A : Args)
+ if (!llvm::is_contained(*DAL, A))
+ DAL->append(A);
+
+ if (!DAL->hasArg(options::OPT_march_EQ))
+ DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ),
+ CudaArchToString(CudaArch::CudaDefault));
+
+ return DAL;
+}
+
+void NVPTXToolChain::addClangTargetOptions(
+ const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadingKind) const {
+ // If we are compiling with a standalone NVPTX toolchain we want to try to
+ // mimic a standard environment as much as possible. So we enable lowering
+ // ctor / dtor functions to global symbols that can be registered.
+ if (Freestanding)
+ CC1Args.append({"-mllvm", "--nvptx-lower-global-ctor-dtor"});
+}
+
+bool NVPTXToolChain::supportsDebugInfoOption(const llvm::opt::Arg *A) const {
+ const Option &O = A->getOption();
+ return (O.matches(options::OPT_gN_Group) &&
+ !O.matches(options::OPT_gmodules)) ||
+ O.matches(options::OPT_g_Flag) ||
+ O.matches(options::OPT_ggdbN_Group) || O.matches(options::OPT_ggdb) ||
+ O.matches(options::OPT_gdwarf) || O.matches(options::OPT_gdwarf_2) ||
+ O.matches(options::OPT_gdwarf_3) || O.matches(options::OPT_gdwarf_4) ||
+ O.matches(options::OPT_gdwarf_5) ||
+ O.matches(options::OPT_gcolumn_info);
}
+void NVPTXToolChain::adjustDebugInfoKind(
+ llvm::codegenoptions::DebugInfoKind &DebugInfoKind,
+ const ArgList &Args) const {
+ switch (mustEmitDebugInfo(Args)) {
+ case DisableDebugInfo:
+ DebugInfoKind = llvm::codegenoptions::NoDebugInfo;
+ break;
+ case DebugDirectivesOnly:
+ DebugInfoKind = llvm::codegenoptions::DebugDirectivesOnly;
+ break;
+ case EmitSameDebugInfoAsHost:
+ // Use same debug info level as the host.
+ break;
+ }
+}
+
+/// CUDA toolchain. Our assembler is ptxas, and our "linker" is fatbinary,
+/// which isn't properly a linker but nonetheless performs the step of stitching
+/// together object files from the assembler into a single blob.
+
+CudaToolChain::CudaToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ToolChain &HostTC, const ArgList &Args)
+ : NVPTXToolChain(D, Triple, HostTC.getTriple(), Args), HostTC(HostTC) {}
+
void CudaToolChain::addClangTargetOptions(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args,
+ const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadingKind) const {
HostTC.addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadingKind);
@@ -686,11 +803,15 @@ 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");
-
- if (DriverArgs.hasFlag(options::OPT_fcuda_approx_transcendentals,
- options::OPT_fno_cuda_approx_transcendentals, false))
- CC1Args.push_back("-fcuda-approx-transcendentals");
+ CC1Args.append(
+ {"-fcuda-is-device", "-mllvm", "-enable-memcpyopt-without-libcalls"});
+
+ // Unsized function arguments used for variadics were introduced in CUDA-9.0
+ // We still do not support generating code that actually uses variadic
+ // arguments yet, but we do need to allow parsing them as recent CUDA
+ // headers rely on that. https://github.com/llvm/llvm-project/issues/58410
+ if (CudaInstallation.version() >= CudaVersion::CUDA_90)
+ CC1Args.push_back("-fcuda-allow-variadic-functions");
}
if (DriverArgs.hasArg(options::OPT_nogpulib))
@@ -711,29 +832,6 @@ void CudaToolChain::addClangTargetOptions(
clang::CudaVersion CudaInstallationVersion = CudaInstallation.version();
- // New CUDA versions often introduce new instructions that are only supported
- // by new PTX version, so we need to raise PTX level to enable them in NVPTX
- // back-end.
- const char *PtxFeature = nullptr;
- switch (CudaInstallationVersion) {
-#define CASE_CUDA_VERSION(CUDA_VER, PTX_VER) \
- case CudaVersion::CUDA_##CUDA_VER: \
- PtxFeature = "+ptx" #PTX_VER; \
- break;
- CASE_CUDA_VERSION(112, 72);
- CASE_CUDA_VERSION(111, 71);
- CASE_CUDA_VERSION(110, 70);
- CASE_CUDA_VERSION(102, 65);
- CASE_CUDA_VERSION(101, 64);
- CASE_CUDA_VERSION(100, 63);
- CASE_CUDA_VERSION(92, 61);
- CASE_CUDA_VERSION(91, 61);
- CASE_CUDA_VERSION(90, 60);
-#undef CASE_CUDA_VERSION
- default:
- PtxFeature = "+ptx42";
- }
- CC1Args.append({"-target-feature", PtxFeature});
if (DriverArgs.hasFlag(options::OPT_fcuda_short_ptr,
options::OPT_fno_cuda_short_ptr, false))
CC1Args.append({"-mllvm", "--nvptx-short-ptr"});
@@ -751,14 +849,11 @@ void CudaToolChain::addClangTargetOptions(
return;
}
- std::string BitcodeSuffix;
- if (DriverArgs.hasFlag(options::OPT_fopenmp_target_new_runtime,
- options::OPT_fno_openmp_target_new_runtime, false))
- BitcodeSuffix = "new-nvptx-" + GpuArch.str();
- else
- BitcodeSuffix = "nvptx-" + GpuArch.str();
+ // Link the bitcode library late if we're using device LTO.
+ if (getDriver().isUsingLTO(/* IsOffload */ true))
+ return;
- addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, BitcodeSuffix,
+ addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, GpuArch.str(),
getTriple());
}
}
@@ -777,33 +872,6 @@ llvm::DenormalMode CudaToolChain::getDefaultDenormalModeForType(
return llvm::DenormalMode::getIEEE();
}
-bool CudaToolChain::supportsDebugInfoOption(const llvm::opt::Arg *A) const {
- const Option &O = A->getOption();
- return (O.matches(options::OPT_gN_Group) &&
- !O.matches(options::OPT_gmodules)) ||
- O.matches(options::OPT_g_Flag) ||
- O.matches(options::OPT_ggdbN_Group) || O.matches(options::OPT_ggdb) ||
- O.matches(options::OPT_gdwarf) || O.matches(options::OPT_gdwarf_2) ||
- O.matches(options::OPT_gdwarf_3) || O.matches(options::OPT_gdwarf_4) ||
- O.matches(options::OPT_gdwarf_5) ||
- O.matches(options::OPT_gcolumn_info);
-}
-
-void CudaToolChain::adjustDebugInfoKind(
- codegenoptions::DebugInfoKind &DebugInfoKind, const ArgList &Args) const {
- switch (mustEmitDebugInfo(Args)) {
- case DisableDebugInfo:
- DebugInfoKind = codegenoptions::NoDebugInfo;
- break;
- case DebugDirectivesOnly:
- DebugInfoKind = codegenoptions::DebugDirectivesOnly;
- break;
- case EmitSameDebugInfoAsHost:
- // Use same debug info level as the host.
- break;
- }
-}
-
void CudaToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
// Check our CUDA version if we're going to include the CUDA headers.
@@ -816,6 +884,19 @@ void CudaToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
}
+std::string CudaToolChain::getInputFilename(const InputInfo &Input) const {
+ // Only object files are changed, for example assembly files keep their .s
+ // extensions. If the user requested device-only compilation don't change it.
+ if (Input.getType() != types::TY_Object || getDriver().offloadDeviceOnly())
+ return ToolChain::getInputFilename(Input);
+
+ // Replace extension for object files with cubin because nvlink relies on
+ // these particular file names.
+ SmallString<256> Filename(ToolChain::getInputFilename(Input));
+ llvm::sys::path::replace_extension(Filename, "cubin");
+ return std::string(Filename);
+}
+
llvm::opt::DerivedArgList *
CudaToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
StringRef BoundArch,
@@ -831,23 +912,27 @@ 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;
+ for (Arg *A : Args)
+ if (!llvm::is_contained(*DAL, A))
+ DAL->append(A);
+
+ if (!DAL->hasArg(options::OPT_march_EQ)) {
+ StringRef Arch = BoundArch;
+ if (Arch.empty()) {
+ auto ArchsOrErr = getSystemGPUArchs(Args);
+ if (!ArchsOrErr) {
+ std::string ErrMsg =
+ llvm::formatv("{0}", llvm::fmt_consume(ArchsOrErr.takeError()));
+ getDriver().Diag(diag::err_drv_undetermined_gpu_arch)
+ << llvm::Triple::getArchTypeName(getArch()) << ErrMsg << "-march";
+ Arch = CudaArchToString(CudaArch::CudaDefault);
+ } else {
+ Arch = Args.MakeArgString(ArchsOrErr->front());
}
}
- if (!IsDuplicate)
- DAL->append(A);
+ DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), Arch);
}
- StringRef Arch = DAL->getLastArgValue(options::OPT_march_EQ);
- if (Arch.empty())
- DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ),
- CLANG_OPENMP_NVPTX_DEFAULT_ARCH);
-
return DAL;
}
@@ -857,19 +942,51 @@ CudaToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
if (!BoundArch.empty()) {
DAL->eraseArg(options::OPT_march_EQ);
- DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), BoundArch);
+ DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ),
+ BoundArch);
}
return DAL;
}
+Expected<SmallVector<std::string>>
+CudaToolChain::getSystemGPUArchs(const ArgList &Args) const {
+ // Detect NVIDIA GPUs availible on the system.
+ std::string Program;
+ if (Arg *A = Args.getLastArg(options::OPT_nvptx_arch_tool_EQ))
+ Program = A->getValue();
+ else
+ Program = GetProgramPath("nvptx-arch");
+
+ auto StdoutOrErr = executeToolChainProgram(Program);
+ if (!StdoutOrErr)
+ return StdoutOrErr.takeError();
+
+ SmallVector<std::string, 1> GPUArchs;
+ for (StringRef Arch : llvm::split((*StdoutOrErr)->getBuffer(), "\n"))
+ if (!Arch.empty())
+ GPUArchs.push_back(Arch.str());
+
+ if (GPUArchs.empty())
+ return llvm::createStringError(std::error_code(),
+ "No NVIDIA GPU detected in the system");
+
+ return std::move(GPUArchs);
+}
+
+Tool *NVPTXToolChain::buildAssembler() const {
+ return new tools::NVPTX::Assembler(*this);
+}
+
+Tool *NVPTXToolChain::buildLinker() const {
+ return new tools::NVPTX::Linker(*this);
+}
+
Tool *CudaToolChain::buildAssembler() const {
return new tools::NVPTX::Assembler(*this);
}
Tool *CudaToolChain::buildLinker() const {
- if (OK == Action::OFK_OpenMP)
- return new tools::NVPTX::OpenMPLinker(*this);
- return new tools::NVPTX::Linker(*this);
+ return new tools::NVPTX::FatBinary(*this);
}
void CudaToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {
@@ -884,6 +1001,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/contrib/llvm-project/clang/lib/Driver/ToolChains/Cuda.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Cuda.h
index 6ae4415a563a..8a053f3393e1 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Cuda.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Cuda.h
@@ -14,7 +14,6 @@
#include "clang/Driver/Multilib.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
-#include "llvm/ADT/Optional.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/VersionTuple.h"
#include <bitset>
@@ -30,11 +29,8 @@ 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;
std::string LibDevicePath;
std::string IncludePath;
llvm::StringMap<std::string> LibDeviceMap;
@@ -62,15 +58,16 @@ 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.
StringRef getBinPath() const { return BinPath; }
/// Get the detected Cuda Include path.
StringRef getIncludePath() const { return IncludePath; }
- /// Get the detected Cuda library path.
- StringRef getLibPath() const { return LibPath; }
/// Get the detected Cuda device library path.
StringRef getLibDevicePath() const { return LibDevicePath; }
/// Get libdevice file for given architecture
@@ -84,85 +81,125 @@ namespace tools {
namespace NVPTX {
// Run ptxas, the NVPTX assembler.
-class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
- public:
- Assembler(const ToolChain &TC) : Tool("NVPTX::Assembler", "ptxas", TC) {}
+class LLVM_LIBRARY_VISIBILITY Assembler final : public Tool {
+public:
+ Assembler(const ToolChain &TC) : Tool("NVPTX::Assembler", "ptxas", TC) {}
- bool hasIntegratedCPP() const override { return false; }
+ bool hasIntegratedCPP() const override { return false; }
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
};
// Runs fatbinary, which combines GPU object files ("cubin" files) and/or PTX
// assembly into a single output file.
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
- public:
- Linker(const ToolChain &TC) : Tool("NVPTX::Linker", "fatbinary", TC) {}
+class LLVM_LIBRARY_VISIBILITY FatBinary : public Tool {
+public:
+ FatBinary(const ToolChain &TC) : Tool("NVPTX::Linker", "fatbinary", TC) {}
- bool hasIntegratedCPP() const override { return false; }
+ bool hasIntegratedCPP() const override { return false; }
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
+ 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 OpenMPLinker : public Tool {
- public:
- OpenMPLinker(const ToolChain &TC)
- : Tool("NVPTX::OpenMPLinker", "nvlink", TC) {}
+// Runs nvlink, which links GPU object files ("cubin" files) into a single file.
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
+public:
+ Linker(const ToolChain &TC) : Tool("NVPTX::Linker", "nvlink", TC) {}
- bool hasIntegratedCPP() const override { return false; }
+ bool hasIntegratedCPP() const override { return false; }
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
};
+void getNVPTXTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args,
+ std::vector<StringRef> &Features);
+
} // end namespace NVPTX
} // end namespace tools
namespace toolchains {
-class LLVM_LIBRARY_VISIBILITY CudaToolChain : public ToolChain {
+class LLVM_LIBRARY_VISIBILITY NVPTXToolChain : public ToolChain {
public:
- CudaToolChain(const Driver &D, const llvm::Triple &Triple,
- const ToolChain &HostTC, const llvm::opt::ArgList &Args,
- const Action::OffloadKind OK);
+ NVPTXToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::Triple &HostTriple, const llvm::opt::ArgList &Args,
+ bool Freestanding);
- const llvm::Triple *getAuxTriple() const override {
- return &HostTC.getTriple();
- }
-
- std::string getInputFilename(const InputInfo &Input) const override;
+ NVPTXToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
llvm::opt::DerivedArgList *
TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
Action::OffloadKind DeviceOffloadKind) const override;
- void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args,
- Action::OffloadKind DeviceOffloadKind) const override;
- llvm::DenormalMode getDefaultDenormalModeForType(
- const llvm::opt::ArgList &DriverArgs, const JobAction &JA,
- const llvm::fltSemantics *FPType = nullptr) const override;
+ void
+ addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadKind) const override;
// Never try to use the integrated assembler with CUDA; always fork out to
// ptxas.
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 IsMathErrnoDefault() const override { return false; }
+
bool supportsDebugInfoOption(const llvm::opt::Arg *A) const override;
- void adjustDebugInfoKind(codegenoptions::DebugInfoKind &DebugInfoKind,
+ void adjustDebugInfoKind(llvm::codegenoptions::DebugInfoKind &DebugInfoKind,
const llvm::opt::ArgList &Args) const override;
- bool IsMathErrnoDefault() const override { return false; }
+
+ // NVPTX supports only DWARF2.
+ unsigned GetDefaultDwarfVersion() const override { return 2; }
+ unsigned getMaxDwarfVersion() const override { return 2; }
+
+ CudaInstallationDetector CudaInstallation;
+
+protected:
+ Tool *buildAssembler() const override; // ptxas.
+ Tool *buildLinker() const override; // nvlink.
+
+private:
+ bool Freestanding = false;
+};
+
+class LLVM_LIBRARY_VISIBILITY CudaToolChain : public NVPTXToolChain {
+public:
+ CudaToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ToolChain &HostTC, const llvm::opt::ArgList &Args);
+
+ const llvm::Triple *getAuxTriple() const override {
+ return &HostTC.getTriple();
+ }
+
+ std::string getInputFilename(const InputInfo &Input) const override;
+
+ llvm::opt::DerivedArgList *
+ TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind) const override;
+ void
+ addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadKind) const override;
+
+ llvm::DenormalMode getDefaultDenormalModeForType(
+ const llvm::opt::ArgList &DriverArgs, const JobAction &JA,
+ const llvm::fltSemantics *FPType = nullptr) const override;
void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
@@ -184,19 +221,16 @@ public:
computeMSVCVersion(const Driver *D,
const llvm::opt::ArgList &Args) const override;
- unsigned GetDefaultDwarfVersion() const override { return 2; }
- // NVPTX supports only DWARF2.
- unsigned getMaxDwarfVersion() const override { return 2; }
-
const ToolChain &HostTC;
- CudaInstallationDetector CudaInstallation;
-protected:
- Tool *buildAssembler() const override; // ptxas
- Tool *buildLinker() const override; // fatbinary (ok, not really a linker)
+ /// Uses nvptx-arch tool to get arch of the system GPU. Will return error
+ /// if unable to find one.
+ virtual Expected<SmallVector<std::string>>
+ getSystemGPUArchs(const llvm::opt::ArgList &Args) const override;
-private:
- const Action::OffloadKind OK;
+protected:
+ Tool *buildAssembler() const override; // ptxas
+ Tool *buildLinker() const override; // fatbinary (ok, not really a linker)
};
} // end namespace toolchains
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Darwin.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Darwin.cpp
index 261f522f6c49..fae8ad1a958a 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -23,9 +23,10 @@
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ScopedPrinter.h"
-#include "llvm/Support/TargetParser.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/TargetParser/TargetParser.h"
+#include "llvm/TargetParser/Triple.h"
#include <cstdlib> // ::getenv
using namespace clang::driver;
@@ -34,7 +35,7 @@ using namespace clang::driver::toolchains;
using namespace clang;
using namespace llvm::opt;
-static const VersionTuple minimumMacCatalystDeploymentTarget() {
+static VersionTuple minimumMacCatalystDeploymentTarget() {
return VersionTuple(13, 1);
}
@@ -44,7 +45,7 @@ llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
// The matching this routine does is fairly pointless, since it is neither the
// complete architecture list, nor a reasonable subset. The problem is that
- // historically the driver driver accepts this and also ties its -march=
+ // historically the driver accepts this and also ties its -march=
// handling to the architecture name, so we need to be careful before removing
// support for it.
@@ -52,14 +53,11 @@ llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
// translation.
return llvm::StringSwitch<llvm::Triple::ArchType>(Str)
- .Cases("ppc", "ppc601", "ppc603", "ppc604", "ppc604e", llvm::Triple::ppc)
- .Cases("ppc750", "ppc7400", "ppc7450", "ppc970", llvm::Triple::ppc)
- .Case("ppc64", llvm::Triple::ppc64)
.Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86)
.Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4",
llvm::Triple::x86)
.Cases("x86_64", "x86_64h", llvm::Triple::x86_64)
- // This is derived from the driver driver.
+ // This is derived from the driver.
.Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm)
.Cases("armv7", "armv7em", "armv7k", "armv7m", llvm::Triple::arm)
.Cases("armv7s", "xscale", llvm::Triple::arm)
@@ -74,7 +72,8 @@ llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
.Default(llvm::Triple::UnknownArch);
}
-void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str) {
+void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str,
+ const ArgList &Args) {
const llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str);
llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(Str);
T.setArch(Arch);
@@ -84,6 +83,17 @@ void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str) {
if (ArchKind == llvm::ARM::ArchKind::ARMV6M ||
ArchKind == llvm::ARM::ArchKind::ARMV7M ||
ArchKind == llvm::ARM::ArchKind::ARMV7EM) {
+ // Don't reject these -version-min= if we have the appropriate triple.
+ if (T.getOS() == llvm::Triple::IOS)
+ for (Arg *A : Args.filtered(options::OPT_mios_version_min_EQ))
+ A->ignoreTargetSpecific();
+ if (T.getOS() == llvm::Triple::WatchOS)
+ for (Arg *A : Args.filtered(options::OPT_mwatchos_version_min_EQ))
+ A->ignoreTargetSpecific();
+ if (T.getOS() == llvm::Triple::TvOS)
+ for (Arg *A : Args.filtered(options::OPT_mtvos_version_min_EQ))
+ A->ignoreTargetSpecific();
+
T.setOS(llvm::Triple::UnknownOS);
T.setObjectFormat(llvm::Triple::MachO);
}
@@ -94,6 +104,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 +124,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 +141,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 &&
@@ -209,20 +219,19 @@ static bool shouldLinkerNotDedup(bool IsLinkerOnlyAction, const ArgList &Args) {
void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
ArgStringList &CmdArgs,
const InputInfoList &Inputs,
- unsigned Version[5], bool LinkerIsLLD,
- bool LinkerIsLLDDarwinNew) const {
+ VersionTuple Version, bool LinkerIsLLD,
+ bool UsePlatformVersion) const {
const Driver &D = getToolChain().getDriver();
const toolchains::MachO &MachOTC = getMachOToolChain();
// Newer linkers support -demangle. Pass it if supported and not disabled by
// the user.
- if ((Version[0] >= 100 || LinkerIsLLD) &&
+ if ((Version >= VersionTuple(100) || LinkerIsLLD) &&
!Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
CmdArgs.push_back("-demangle");
- // FIXME: Pass most of the flags below that check Version if LinkerIsLLD too.
-
- if (Args.hasArg(options::OPT_rdynamic) && Version[0] >= 137)
+ if (Args.hasArg(options::OPT_rdynamic) &&
+ (Version >= VersionTuple(137) || LinkerIsLLD))
CmdArgs.push_back("-export_dynamic");
// If we are using App Extension restrictions, pass a flag to the linker
@@ -231,7 +240,8 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
options::OPT_fno_application_extension, false))
CmdArgs.push_back("-application_extension");
- if (D.isUsingLTO() && Version[0] >= 116 && NeedsTempPath(Inputs)) {
+ if (D.isUsingLTO() && (Version >= VersionTuple(116) || LinkerIsLLD) &&
+ NeedsTempPath(Inputs)) {
std::string TmpPathName;
if (D.getLTOMode() == LTOK_Full) {
// If we are using full LTO, then automatically create a temporary file
@@ -260,7 +270,7 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
// clang version won't work anyways.
// lld is built at the same revision as clang and statically links in
// LLVM libraries, so it doesn't need libLTO.dylib.
- if (Version[0] >= 133 && !LinkerIsLLD) {
+ if (Version >= VersionTuple(133) && !LinkerIsLLD) {
// Search for libLTO in <InstalledDir>/../lib/libLTO.dylib
StringRef P = llvm::sys::path::parent_path(D.Dir);
SmallString<128> LibLTOPath(P);
@@ -270,8 +280,11 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
CmdArgs.push_back(C.getArgs().MakeArgString(LibLTOPath));
}
- // ld64 version 262 and above run the deduplicate pass by default.
- if (Version[0] >= 262 && shouldLinkerNotDedup(C.getJobs().empty(), Args))
+ // ld64 version 262 and above runs the deduplicate pass by default.
+ // FIXME: lld doesn't dedup by default. Should we pass `--icf=safe`
+ // if `!shouldLinkerNotDedup()` if LinkerIsLLD here?
+ if (Version >= VersionTuple(262) &&
+ shouldLinkerNotDedup(C.getJobs().empty(), Args))
CmdArgs.push_back("-no_deduplicate");
// Derived from the "link" spec.
@@ -343,7 +356,7 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
Args.AddAllArgs(CmdArgs, options::OPT_init);
// Add the deployment target.
- if (Version[0] >= 520 || LinkerIsLLDDarwinNew)
+ if (Version >= VersionTuple(520) || LinkerIsLLD || UsePlatformVersion)
MachOTC.addPlatformVersionArgs(Args, CmdArgs);
else
MachOTC.addMinVersionArgs(Args, CmdArgs);
@@ -369,7 +382,9 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
// Check if the toolchain supports bitcode build flow.
if (MachOTC.SupportsEmbeddedBitcode()) {
CmdArgs.push_back("-bitcode_bundle");
- if (C.getDriver().embedBitcodeMarkerOnly() && Version[0] >= 278) {
+ // FIXME: Pass this if LinkerIsLLD too, once it implements this flag.
+ if (C.getDriver().embedBitcodeMarkerOnly() &&
+ Version >= VersionTuple(278)) {
CmdArgs.push_back("-bitcode_process_mode");
CmdArgs.push_back("marker");
}
@@ -389,6 +404,13 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
}
}
+ if (Args.hasArg(options::OPT_mkernel) ||
+ Args.hasArg(options::OPT_fapple_kext) ||
+ Args.hasArg(options::OPT_ffreestanding)) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-disable-atexit-based-global-dtor-lowering");
+ }
+
Args.AddLastArg(CmdArgs, options::OPT_prebind);
Args.AddLastArg(CmdArgs, options::OPT_noprebind);
Args.AddLastArg(CmdArgs, options::OPT_nofixprebinding);
@@ -438,6 +460,23 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
Args.AddAllArgs(CmdArgs, options::OPT_dylinker__install__name);
Args.AddLastArg(CmdArgs, options::OPT_dylinker);
Args.AddLastArg(CmdArgs, options::OPT_Mach);
+
+ if (LinkerIsLLD) {
+ if (auto *CSPGOGenerateArg = getLastCSProfileGenerateArg(Args)) {
+ SmallString<128> Path(CSPGOGenerateArg->getNumValues() == 0
+ ? ""
+ : CSPGOGenerateArg->getValue());
+ llvm::sys::path::append(Path, "default_%m.profraw");
+ CmdArgs.push_back("--cs-profile-generate");
+ CmdArgs.push_back(Args.MakeArgString(Twine("--cs-profile-path=") + Path));
+ } else if (auto *ProfileUseArg = getLastProfileUseArg(Args)) {
+ SmallString<128> Path(
+ ProfileUseArg->getNumValues() == 0 ? "" : ProfileUseArg->getValue());
+ if (Path.empty() || llvm::sys::fs::is_directory(Path))
+ llvm::sys::path::append(Path, "default.profdata");
+ CmdArgs.push_back(Args.MakeArgString(Twine("--cs-profile-path=") + Path));
+ }
+ }
}
/// Determine whether we are linking the ObjC runtime.
@@ -518,6 +557,8 @@ static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs,
}
}
+static void AppendPlatformPrefix(SmallString<128> &Path, const llvm::Triple &T);
+
void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -544,26 +585,25 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("touch"));
CmdArgs.push_back(Output.getFilename());
- C.addCommand(std::make_unique<Command>(
- JA, *this, ResponseFileSupport::None(), Exec, CmdArgs, None, Output));
+ C.addCommand(std::make_unique<Command>(JA, *this,
+ ResponseFileSupport::None(), Exec,
+ CmdArgs, std::nullopt, Output));
return;
}
- unsigned Version[5] = {0, 0, 0, 0, 0};
- if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) {
- if (!Driver::GetReleaseVersion(A->getValue(), Version))
- getToolChain().getDriver().Diag(diag::err_drv_invalid_version_number)
- << A->getAsString(Args);
- }
+ VersionTuple Version = getMachOToolChain().getLinkerVersion(Args);
- bool LinkerIsLLD, LinkerIsLLDDarwinNew;
- const char *Exec = Args.MakeArgString(
- getToolChain().GetLinkerPath(&LinkerIsLLD, &LinkerIsLLDDarwinNew));
+ bool LinkerIsLLD;
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetLinkerPath(&LinkerIsLLD));
+
+ // xrOS always uses -platform-version.
+ bool UsePlatformVersion = getToolChain().getTriple().isXROS();
// I'm not sure why this particular decomposition exists in gcc, but
// we follow suite for ease of comparison.
AddLinkArgs(C, Args, CmdArgs, Inputs, Version, LinkerIsLLD,
- LinkerIsLLDDarwinNew);
+ UsePlatformVersion);
if (willEmitRemarks(Args) &&
checkRemarksOptions(getToolChain().getDriver(), Args,
@@ -577,10 +617,6 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (getMachOToolChain().getMachOArchName(Args) == "arm64") {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-enable-machine-outliner");
-
- // Outline from linkonceodr functions by default in LTO.
- CmdArgs.push_back("-mllvm");
- CmdArgs.push_back("-enable-linkonceodr-outlining");
}
} else {
// Disable all outlining behaviour if we have mno-outline. We need to do
@@ -591,6 +627,12 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ // Outline from linkonceodr functions by default in LTO, whenever the outliner
+ // is enabled. Note that the target may enable the machine outliner
+ // independently of -moutline.
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-enable-linkonceodr-outlining");
+
// Setup statistics file output.
SmallString<128> StatsFile =
getStatsFileName(Args, Output, Inputs[0], getToolChain().getDriver());
@@ -601,9 +643,9 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// It seems that the 'e' option is completely ignored for dynamic executables
// (the default), and with static executables, the last one wins, as expected.
- Args.AddAllArgs(CmdArgs, {options::OPT_d_Flag, options::OPT_s, options::OPT_t,
- options::OPT_Z_Flag, options::OPT_u_Group,
- options::OPT_e, options::OPT_r});
+ Args.addAllArgs(CmdArgs,
+ {options::OPT_d_Flag, options::OPT_s, options::OPT_t,
+ options::OPT_Z_Flag, options::OPT_u_Group, options::OPT_r});
// Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading
// members of static archive libraries which implement Objective-C classes or
@@ -637,6 +679,13 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
InputFileList.push_back(II.getFilename());
}
+ // Additional linker set-up and flags for Fortran. This is required in order
+ // to generate executables.
+ if (getToolChain().getDriver().IsFlangMode()) {
+ addFortranRuntimeLibraryPath(getToolChain(), Args, CmdArgs);
+ addFortranRuntimeLibs(getToolChain(), Args, CmdArgs);
+ }
+
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
addOpenMPRuntime(CmdArgs, getToolChain(), Args);
@@ -714,8 +763,37 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ // Add non-standard, platform-specific search paths, e.g., for DriverKit:
+ // -L<sysroot>/System/DriverKit/usr/lib
+ // -F<sysroot>/System/DriverKit/System/Library/Framework
+ {
+ bool NonStandardSearchPath = false;
+ const auto &Triple = getToolChain().getTriple();
+ if (Triple.isDriverKit()) {
+ // ld64 fixed the implicit -F and -L paths in ld64-605.1+.
+ NonStandardSearchPath =
+ Version.getMajor() < 605 ||
+ (Version.getMajor() == 605 && Version.getMinor().value_or(0) < 1);
+ }
+
+ if (NonStandardSearchPath) {
+ if (auto *Sysroot = Args.getLastArg(options::OPT_isysroot)) {
+ auto AddSearchPath = [&](StringRef Flag, StringRef SearchPath) {
+ SmallString<128> P(Sysroot->getValue());
+ AppendPlatformPrefix(P, Triple);
+ llvm::sys::path::append(P, SearchPath);
+ if (getToolChain().getVFS().exists(P)) {
+ CmdArgs.push_back(Args.MakeArgString(Flag + P));
+ }
+ };
+ AddSearchPath("-L", "/usr/lib");
+ AddSearchPath("-F", "/System/Library/Frameworks");
+ }
+ }
+ }
+
ResponseFileSupport ResponseSupport;
- if (Version[0] >= 705 || LinkerIsLLDDarwinNew) {
+ if (Version >= VersionTuple(705) || LinkerIsLLD) {
ResponseSupport = ResponseFileSupport::AtFileUTF8();
} else {
// For older versions of the linker, use the legacy filelist method instead.
@@ -729,6 +807,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,
@@ -823,13 +949,8 @@ types::ID MachO::LookupTypeForExtension(StringRef Ext) const {
bool MachO::HasNativeLLVMSupport() const { return true; }
ToolChain::CXXStdlibType Darwin::GetDefaultCXXStdlibType() const {
- // Default to use libc++ on OS X 10.9+ and iOS 7+.
- if ((isTargetMacOSBased() && !isMacosxVersionLT(10, 9)) ||
- (isTargetIOSBased() && !isIPhoneOSVersionLT(7, 0)) ||
- isTargetWatchOSBased())
- return ToolChain::CST_Libcxx;
-
- return ToolChain::CST_Libstdcxx;
+ // Always use libc++ by default
+ return ToolChain::CST_Libcxx;
}
/// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0.
@@ -838,6 +959,13 @@ ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const {
return ObjCRuntime(ObjCRuntime::WatchOS, TargetVersion);
if (isTargetIOSBased())
return ObjCRuntime(ObjCRuntime::iOS, TargetVersion);
+ if (isTargetXROS()) {
+ // XROS uses the iOS runtime.
+ auto T = llvm::Triple(Twine("arm64-apple-") +
+ llvm::Triple::getOSTypeName(llvm::Triple::XROS) +
+ TargetVersion.getAsString());
+ return ObjCRuntime(ObjCRuntime::iOS, T.getiOSVersion());
+ }
if (isNonFragile)
return ObjCRuntime(ObjCRuntime::MacOSX, TargetVersion);
return ObjCRuntime(ObjCRuntime::FragileMacOSX, TargetVersion);
@@ -845,7 +973,7 @@ ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const {
/// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2.
bool Darwin::hasBlocksRuntime() const {
- if (isTargetWatchOSBased())
+ if (isTargetWatchOSBased() || isTargetDriverKit() || isTargetXROS())
return true;
else if (isTargetIOSBased())
return !isIPhoneOSVersionLT(3, 2);
@@ -857,12 +985,12 @@ bool Darwin::hasBlocksRuntime() const {
void Darwin::AddCudaIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
- CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
+ CudaInstallation->AddCudaIncludeArgs(DriverArgs, CC1Args);
}
void Darwin::AddHIPIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
- RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
+ RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args);
}
// This is just a MachO name translation routine and there's no
@@ -894,13 +1022,13 @@ static const char *ArmMachOArchNameCPU(StringRef CPU) {
// FIXME: Make sure this MachO triple mangling is really necessary.
// ARMv5* normalises to ARMv5.
- if (Arch.startswith("armv5"))
+ if (Arch.starts_with("armv5"))
Arch = Arch.substr(0, 5);
// ARMv6*, except ARMv6M, normalises to ARMv6.
- else if (Arch.startswith("armv6") && !Arch.endswith("6m"))
+ else if (Arch.starts_with("armv6") && !Arch.ends_with("6m"))
Arch = Arch.substr(0, 5);
// ARMv7A normalises to ARMv7.
- else if (Arch.endswith("v7a"))
+ else if (Arch.ends_with("v7a"))
Arch = Arch.substr(0, 5);
return Arch.data();
}
@@ -933,6 +1061,27 @@ StringRef MachO::getMachOArchName(const ArgList &Args) const {
}
}
+VersionTuple MachO::getLinkerVersion(const llvm::opt::ArgList &Args) const {
+ if (LinkerVersion) {
+#ifndef NDEBUG
+ VersionTuple NewLinkerVersion;
+ if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ))
+ (void)NewLinkerVersion.tryParse(A->getValue());
+ assert(NewLinkerVersion == LinkerVersion);
+#endif
+ return *LinkerVersion;
+ }
+
+ VersionTuple NewLinkerVersion;
+ if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ))
+ if (NewLinkerVersion.tryParse(A->getValue()))
+ getDriver().Diag(diag::err_drv_invalid_version_number)
+ << A->getAsString(Args);
+
+ LinkerVersion = NewLinkerVersion;
+ return *LinkerVersion;
+}
+
Darwin::~Darwin() {}
MachO::~MachO() {}
@@ -951,8 +1100,12 @@ std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args,
Str += "watchos";
else if (isTargetTvOSBased())
Str += "tvos";
+ else if (isTargetDriverKit())
+ Str += "driverkit";
else if (isTargetIOSBased() || isTargetMacCatalyst())
Str += "ios";
+ else if (isTargetXROS())
+ Str += llvm::Triple::getOSTypeName(llvm::Triple::XROS);
else
Str += "macosx";
Str += getTripleTargetVersion().getAsString();
@@ -982,6 +1135,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);
}
@@ -1031,6 +1188,8 @@ void DarwinClang::AddLinkARCArgs(const ArgList &Args,
// ARC runtime is supported everywhere on arm64e.
if (getTriple().isArm64e())
return;
+ if (isTargetXROS())
+ return;
ObjCRuntime runtime = getDefaultObjCRuntime(/*nonfragile*/ true);
@@ -1041,25 +1200,38 @@ void DarwinClang::AddLinkARCArgs(const ArgList &Args,
SmallString<128> P(getDriver().ClangExecutable);
llvm::sys::path::remove_filename(P); // 'clang'
llvm::sys::path::remove_filename(P); // 'bin'
+ llvm::sys::path::append(P, "lib", "arc");
// 'libarclite' usually lives in the same toolchain as 'clang'. However, the
// Swift open source toolchains for macOS distribute Clang without libarclite.
// In that case, to allow the linker to find 'libarclite', we point to the
// 'libarclite' in the XcodeDefault toolchain instead.
- if (getXcodeDeveloperPath(P).empty()) {
- if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
+ if (!getVFS().exists(P)) {
+ auto updatePath = [&](const Arg *A) {
// Try to infer the path to 'libarclite' in the toolchain from the
// specified SDK path.
StringRef XcodePathForSDK = getXcodeDeveloperPath(A->getValue());
- if (!XcodePathForSDK.empty()) {
- P = XcodePathForSDK;
- llvm::sys::path::append(P, "Toolchains/XcodeDefault.xctoolchain/usr");
- }
+ if (XcodePathForSDK.empty())
+ return false;
+
+ P = XcodePathForSDK;
+ llvm::sys::path::append(P, "Toolchains/XcodeDefault.xctoolchain/usr",
+ "lib", "arc");
+ return getVFS().exists(P);
+ };
+
+ bool updated = false;
+ if (const Arg *A = Args.getLastArg(options::OPT_isysroot))
+ updated = updatePath(A);
+
+ if (!updated) {
+ if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ))
+ updatePath(A);
}
}
CmdArgs.push_back("-force_load");
- llvm::sys::path::append(P, "lib", "arc", "libarclite_");
+ llvm::sys::path::append(P, "libarclite_");
// Mash in the platform.
if (isTargetWatchOSSimulator())
P += "watchsimulator";
@@ -1077,6 +1249,9 @@ void DarwinClang::AddLinkARCArgs(const ArgList &Args,
P += "macosx";
P += ".a";
+ if (!getVFS().exists(P))
+ getDriver().Diag(clang::diag::err_drv_darwin_sdk_missing_arclite) << P;
+
CmdArgs.push_back(Args.MakeArgString(P));
}
@@ -1102,8 +1277,9 @@ void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
DarwinLibName += getOSLibraryNameSuffix();
DarwinLibName += IsShared ? "_dynamic.dylib" : ".a";
SmallString<128> Dir(getDriver().ResourceDir);
- llvm::sys::path::append(
- Dir, "lib", (Opts & RLO_IsEmbedded) ? "macho_embedded" : "darwin");
+ llvm::sys::path::append(Dir, "lib", "darwin");
+ if (Opts & RLO_IsEmbedded)
+ llvm::sys::path::append(Dir, "macho_embedded");
SmallString<128> P(Dir);
llvm::sys::path::append(P, DarwinLibName);
@@ -1121,7 +1297,7 @@ void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
// rpaths. This is currently true from this place, but we need to be
// careful if this function is ever called before user's rpaths are emitted.
if (Opts & RLO_AddRPath) {
- assert(DarwinLibName.endswith(".dylib") && "must be a dynamic library");
+ assert(DarwinLibName.ends_with(".dylib") && "must be a dynamic library");
// Add @executable_path to rpath to support having the dylib copied with
// the executable.
@@ -1147,6 +1323,10 @@ StringRef Darwin::getPlatformFamily() const {
return "AppleTV";
case DarwinPlatformKind::WatchOS:
return "Watch";
+ case DarwinPlatformKind::DriverKit:
+ return "DriverKit";
+ case DarwinPlatformKind::XROS:
+ return "XR";
}
llvm_unreachable("Unsupported platform");
}
@@ -1157,8 +1337,8 @@ StringRef Darwin::getSDKName(StringRef isysroot) {
auto EndSDK = llvm::sys::path::rend(isysroot);
for (auto IT = BeginSDK; IT != EndSDK; ++IT) {
StringRef SDK = *IT;
- if (SDK.endswith(".sdk"))
- return SDK.slice(0, SDK.size() - 4);
+ if (SDK.ends_with(".sdk"))
+ return SDK.slice(0, SDK.size() - 4);
}
return "";
}
@@ -1178,6 +1358,11 @@ StringRef Darwin::getOSLibraryNameSuffix(bool IgnoreSim) const {
case DarwinPlatformKind::WatchOS:
return TargetEnvironment == NativeEnvironment || IgnoreSim ? "watchos"
: "watchossim";
+ case DarwinPlatformKind::XROS:
+ return TargetEnvironment == NativeEnvironment || IgnoreSim ? "xros"
+ : "xrossim";
+ case DarwinPlatformKind::DriverKit:
+ return "driverkit";
}
llvm_unreachable("Unsupported platform");
}
@@ -1229,20 +1414,14 @@ void Darwin::addProfileRTLibs(const ArgList &Args,
// If we have a symbol export directive and we're linking in the profile
// runtime, automatically export symbols necessary to implement some of the
// runtime's functionality.
- if (hasExportSymbolDirective(Args)) {
- if (ForGCOV) {
- addExportedSymbol(CmdArgs, "___gcov_dump");
- addExportedSymbol(CmdArgs, "___gcov_reset");
- addExportedSymbol(CmdArgs, "_writeout_fn_list");
- addExportedSymbol(CmdArgs, "_reset_fn_list");
- } else {
- addExportedSymbol(CmdArgs, "___llvm_profile_filename");
- addExportedSymbol(CmdArgs, "___llvm_profile_raw_version");
- }
- addExportedSymbol(CmdArgs, "_lprofDirMode");
+ if (hasExportSymbolDirective(Args) && ForGCOV) {
+ addExportedSymbol(CmdArgs, "___gcov_dump");
+ addExportedSymbol(CmdArgs, "___gcov_reset");
+ addExportedSymbol(CmdArgs, "_writeout_fn_list");
+ addExportedSymbol(CmdArgs, "_reset_fn_list");
}
- // Align __llvm_prf_{cnts,data} sections to the maximum expected page
+ // Align __llvm_prf_{cnts,bits,data} sections to the maximum expected page
// alignment. This allows profile counters to be mmap()'d to disk. Note that
// it's not enough to just page-align __llvm_prf_cnts: the following section
// must also be page-aligned so that its data is not clobbered by mmap().
@@ -1252,7 +1431,7 @@ void Darwin::addProfileRTLibs(const ArgList &Args,
// extra alignment also allows the same binary to be used with/without sync
// enabled.
if (!ForGCOV) {
- for (auto IPSK : {llvm::IPSK_cnts, llvm::IPSK_data}) {
+ for (auto IPSK : {llvm::IPSK_cnts, llvm::IPSK_bitmap, llvm::IPSK_data}) {
addSectalignToPage(
Args, CmdArgs, "__DATA",
llvm::getInstrProfSectionName(IPSK, llvm::Triple::MachO,
@@ -1273,7 +1452,7 @@ ToolChain::RuntimeLibType DarwinClang::GetRuntimeLibType(
const ArgList &Args) const {
if (Arg* A = Args.getLastArg(options::OPT_rtlib_EQ)) {
StringRef Value = A->getValue();
- if (Value != "compiler-rt")
+ if (Value != "compiler-rt" && Value != "platform")
getDriver().Diag(clang::diag::err_drv_unsupported_rtlib_for_platform)
<< Value << "darwin";
}
@@ -1305,27 +1484,58 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
return;
}
- const SanitizerArgs &Sanitize = getSanitizerArgs();
- if (Sanitize.needsAsanRt())
- AddLinkSanitizerLibArgs(Args, CmdArgs, "asan");
- if (Sanitize.needsLsanRt())
- AddLinkSanitizerLibArgs(Args, CmdArgs, "lsan");
- if (Sanitize.needsUbsanRt())
- AddLinkSanitizerLibArgs(Args, CmdArgs,
- Sanitize.requiresMinimalRuntime() ? "ubsan_minimal"
- : "ubsan",
- Sanitize.needsSharedRt());
- if (Sanitize.needsTsanRt())
- AddLinkSanitizerLibArgs(Args, CmdArgs, "tsan");
- if (Sanitize.needsFuzzer() && !Args.hasArg(options::OPT_dynamiclib)) {
- AddLinkSanitizerLibArgs(Args, CmdArgs, "fuzzer", /*shared=*/false);
+ const SanitizerArgs &Sanitize = getSanitizerArgs(Args);
- // Libfuzzer is written in C++ and requires libcxx.
- AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (!Sanitize.needsSharedRt()) {
+ const char *sanitizer = nullptr;
+ if (Sanitize.needsUbsanRt()) {
+ sanitizer = "UndefinedBehaviorSanitizer";
+ } else if (Sanitize.needsAsanRt()) {
+ sanitizer = "AddressSanitizer";
+ } else if (Sanitize.needsTsanRt()) {
+ sanitizer = "ThreadSanitizer";
+ }
+ if (sanitizer) {
+ getDriver().Diag(diag::err_drv_unsupported_static_sanitizer_darwin)
+ << sanitizer;
+ return;
+ }
}
- if (Sanitize.needsStatsRt()) {
- AddLinkRuntimeLib(Args, CmdArgs, "stats_client", RLO_AlwaysLink);
- AddLinkSanitizerLibArgs(Args, CmdArgs, "stats");
+
+ if (Sanitize.linkRuntimes()) {
+ if (Sanitize.needsAsanRt()) {
+ if (Sanitize.needsStableAbi()) {
+ AddLinkSanitizerLibArgs(Args, CmdArgs, "asan_abi", /*shared=*/false);
+ } else {
+ assert(Sanitize.needsSharedRt() &&
+ "Static sanitizer runtimes not supported");
+ AddLinkSanitizerLibArgs(Args, CmdArgs, "asan");
+ }
+ }
+ if (Sanitize.needsLsanRt())
+ AddLinkSanitizerLibArgs(Args, CmdArgs, "lsan");
+ if (Sanitize.needsUbsanRt()) {
+ assert(Sanitize.needsSharedRt() &&
+ "Static sanitizer runtimes not supported");
+ AddLinkSanitizerLibArgs(
+ Args, CmdArgs,
+ Sanitize.requiresMinimalRuntime() ? "ubsan_minimal" : "ubsan");
+ }
+ if (Sanitize.needsTsanRt()) {
+ assert(Sanitize.needsSharedRt() &&
+ "Static sanitizer runtimes not supported");
+ AddLinkSanitizerLibArgs(Args, CmdArgs, "tsan");
+ }
+ if (Sanitize.needsFuzzer() && !Args.hasArg(options::OPT_dynamiclib)) {
+ AddLinkSanitizerLibArgs(Args, CmdArgs, "fuzzer", /*shared=*/false);
+
+ // Libfuzzer is written in C++ and requires libcxx.
+ AddCXXStdlibLibArgs(Args, CmdArgs);
+ }
+ if (Sanitize.needsStatsRt()) {
+ AddLinkRuntimeLib(Args, CmdArgs, "stats_client", RLO_AlwaysLink);
+ AddLinkSanitizerLibArgs(Args, CmdArgs, "stats");
+ }
}
const XRayArgs &XRay = getXRayArgs();
@@ -1335,9 +1545,15 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
AddLinkRuntimeLib(Args, CmdArgs, "xray-fdr");
}
+ if (isTargetDriverKit() && !Args.hasArg(options::OPT_nodriverkitlib)) {
+ CmdArgs.push_back("-framework");
+ CmdArgs.push_back("DriverKit");
+ }
+
// Otherwise link libSystem, then the dynamic runtime library, and finally any
// target specific static runtime library.
- CmdArgs.push_back("-lSystem");
+ if (!isTargetDriverKit())
+ CmdArgs.push_back("-lSystem");
// Select the dynamic runtime library and the target specific static library.
if (isTargetIOSBased()) {
@@ -1356,17 +1572,19 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
/// If the macOS SDK version is the same or earlier than the system version,
/// then the SDK version is returned. Otherwise the system version is returned.
static std::string getSystemOrSDKMacOSVersion(StringRef MacOSSDKVersion) {
- unsigned Major, Minor, Micro;
llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
if (!SystemTriple.isMacOSX())
return std::string(MacOSSDKVersion);
- SystemTriple.getMacOSXVersion(Major, Minor, Micro);
- VersionTuple SystemVersion(Major, Minor, Micro);
+ VersionTuple SystemVersion;
+ SystemTriple.getMacOSXVersion(SystemVersion);
+
+ unsigned Major, Minor, Micro;
bool HadExtra;
if (!Driver::GetReleaseVersion(MacOSSDKVersion, Major, Minor, Micro,
HadExtra))
return std::string(MacOSSDKVersion);
VersionTuple SDKVersion(Major, Minor, Micro);
+
if (SDKVersion > SystemVersion)
return SystemVersion.getAsString();
return std::string(MacOSSDKVersion);
@@ -1379,6 +1597,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.
@@ -1426,18 +1646,23 @@ struct DarwinPlatform {
/// Returns true if the simulator environment can be inferred from the arch.
bool canInferSimulatorFromArch() const { return InferSimulatorFromArch; }
+ const std::optional<llvm::Triple> &getTargetVariantTriple() const {
+ return TargetVariantTriple;
+ }
+
/// Adds the -m<os>-version-min argument to the compiler invocation.
void addOSVersionMinArgument(DerivedArgList &Args, const OptTable &Opts) {
if (Argument)
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:
- Opt = options::OPT_mmacosx_version_min_EQ;
+ Opt = options::OPT_mmacos_version_min_EQ;
break;
case DarwinPlatformKind::IPhoneOS:
- Opt = options::OPT_miphoneos_version_min_EQ;
+ Opt = options::OPT_mios_version_min_EQ;
break;
case DarwinPlatformKind::TvOS:
Opt = options::OPT_mtvos_version_min_EQ;
@@ -1445,6 +1670,12 @@ struct DarwinPlatform {
case DarwinPlatformKind::WatchOS:
Opt = options::OPT_mwatchos_version_min_EQ;
break;
+ case DarwinPlatformKind::XROS:
+ // xrOS always explicitly provides a version in the triple.
+ return;
+ case DarwinPlatformKind::DriverKit:
+ // DriverKit always explicitly provides a version in the triple.
+ return;
}
Argument = Args.MakeJoinedArg(nullptr, Opts.getOption(Opt), OSVersion);
Args.append(Argument);
@@ -1455,6 +1686,7 @@ struct DarwinPlatform {
std::string getAsString(DerivedArgList &Args, const OptTable &Opts) {
switch (Kind) {
case TargetArg:
+ case MTargetOSArg:
case OSVersionArg:
case InferredFromSDK:
case InferredFromArch:
@@ -1466,45 +1698,72 @@ 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 std::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, std::nullopt)) {
NativeTargetVersion = *MacOSVersion;
}
}
}
- Result.Environment = DarwinEnvironmentKind::MacCatalyst;
- Result.NativeTargetVersion = NativeTargetVersion;
+ // In a zippered build, we could be building for a macOS target that's
+ // lower than the version that's implied by the OS version. In that case
+ // we need to use the minimum version as the native target version.
+ if (TargetVariantTriple) {
+ auto TargetVariantVersion = TargetVariantTriple->getOSVersion();
+ if (TargetVariantVersion.getMajor()) {
+ if (TargetVariantVersion < NativeTargetVersion)
+ NativeTargetVersion = TargetVariantVersion;
+ }
+ }
break;
}
default:
break;
}
+ }
+
+ static DarwinPlatform
+ createFromTarget(const llvm::Triple &TT, StringRef OSVersion, Arg *A,
+ std::optional<llvm::Triple> TargetVariantTriple,
+ const std::optional<DarwinSDKInfo> &SDKInfo) {
+ DarwinPlatform Result(TargetArg, getPlatformFromOS(TT.getOS()), OSVersion,
+ A);
+ VersionTuple OsVersion = TT.getOSVersion();
+ if (OsVersion.getMajor() == 0)
+ Result.HasOSVersion = false;
+ Result.TargetVariantTriple = TargetVariantTriple;
+ Result.setEnvironment(TT.getEnvironment(), OsVersion, SDKInfo);
return Result;
}
- static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform,
- Arg *A) {
- return DarwinPlatform(OSVersionArg, Platform, A);
+ static DarwinPlatform
+ createFromMTargetOS(llvm::Triple::OSType OS, VersionTuple OSVersion,
+ llvm::Triple::EnvironmentType Environment, Arg *A,
+ const std::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, Arg *A,
+ bool IsSimulator) {
+ DarwinPlatform Result{OSVersionArg, Platform, A};
+ if (IsSimulator)
+ Result.Environment = DarwinEnvironmentKind::Simulator;
+ return Result;
}
static DarwinPlatform createDeploymentTargetEnv(DarwinPlatformKind Platform,
StringRef EnvVarName,
@@ -1559,6 +1818,10 @@ private:
return DarwinPlatformKind::TvOS;
case llvm::Triple::WatchOS:
return DarwinPlatformKind::WatchOS;
+ case llvm::Triple::XROS:
+ return DarwinPlatformKind::XROS;
+ case llvm::Triple::DriverKit:
+ return DarwinPlatformKind::DriverKit;
default:
llvm_unreachable("Unable to infer Darwin variant");
}
@@ -1572,15 +1835,16 @@ private:
bool HasOSVersion = true, InferSimulatorFromArch = true;
Arg *Argument;
StringRef EnvVarName;
+ std::optional<llvm::Triple> TargetVariantTriple;
};
/// Returns the deployment target that's specified using the -m<os>-version-min
/// argument.
-Optional<DarwinPlatform>
+std::optional<DarwinPlatform>
getDeploymentTargetFromOSVersionArg(DerivedArgList &Args,
const Driver &TheDriver) {
- Arg *OSXVersion = Args.getLastArg(options::OPT_mmacosx_version_min_EQ);
- Arg *iOSVersion = Args.getLastArg(options::OPT_miphoneos_version_min_EQ,
+ Arg *macOSVersion = Args.getLastArg(options::OPT_mmacos_version_min_EQ);
+ Arg *iOSVersion = Args.getLastArg(options::OPT_mios_version_min_EQ,
options::OPT_mios_simulator_version_min_EQ);
Arg *TvOSVersion =
Args.getLastArg(options::OPT_mtvos_version_min_EQ,
@@ -1588,37 +1852,47 @@ getDeploymentTargetFromOSVersionArg(DerivedArgList &Args,
Arg *WatchOSVersion =
Args.getLastArg(options::OPT_mwatchos_version_min_EQ,
options::OPT_mwatchos_simulator_version_min_EQ);
- if (OSXVersion) {
+ if (macOSVersion) {
if (iOSVersion || TvOSVersion || WatchOSVersion) {
TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
- << OSXVersion->getAsString(Args)
+ << macOSVersion->getAsString(Args)
<< (iOSVersion ? iOSVersion
: TvOSVersion ? TvOSVersion : WatchOSVersion)
->getAsString(Args);
}
- return DarwinPlatform::createOSVersionArg(Darwin::MacOS, OSXVersion);
+ return DarwinPlatform::createOSVersionArg(Darwin::MacOS, macOSVersion,
+ /*IsSimulator=*/false);
} else if (iOSVersion) {
if (TvOSVersion || WatchOSVersion) {
TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
<< iOSVersion->getAsString(Args)
<< (TvOSVersion ? TvOSVersion : WatchOSVersion)->getAsString(Args);
}
- return DarwinPlatform::createOSVersionArg(Darwin::IPhoneOS, iOSVersion);
+ return DarwinPlatform::createOSVersionArg(
+ Darwin::IPhoneOS, iOSVersion,
+ iOSVersion->getOption().getID() ==
+ options::OPT_mios_simulator_version_min_EQ);
} else if (TvOSVersion) {
if (WatchOSVersion) {
TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
<< TvOSVersion->getAsString(Args)
<< WatchOSVersion->getAsString(Args);
}
- return DarwinPlatform::createOSVersionArg(Darwin::TvOS, TvOSVersion);
+ return DarwinPlatform::createOSVersionArg(
+ Darwin::TvOS, TvOSVersion,
+ TvOSVersion->getOption().getID() ==
+ options::OPT_mtvos_simulator_version_min_EQ);
} else if (WatchOSVersion)
- return DarwinPlatform::createOSVersionArg(Darwin::WatchOS, WatchOSVersion);
- return None;
+ return DarwinPlatform::createOSVersionArg(
+ Darwin::WatchOS, WatchOSVersion,
+ WatchOSVersion->getOption().getID() ==
+ options::OPT_mwatchos_simulator_version_min_EQ);
+ return std::nullopt;
}
/// Returns the deployment target that's specified using the
/// OS_DEPLOYMENT_TARGET environment variable.
-Optional<DarwinPlatform>
+std::optional<DarwinPlatform>
getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver,
const llvm::Triple &Triple) {
std::string Targets[Darwin::LastDarwinPlatform + 1];
@@ -1627,10 +1901,11 @@ getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver,
"IPHONEOS_DEPLOYMENT_TARGET",
"TVOS_DEPLOYMENT_TARGET",
"WATCHOS_DEPLOYMENT_TARGET",
+ "DRIVERKIT_DEPLOYMENT_TARGET",
};
- static_assert(llvm::array_lengthof(EnvVars) == Darwin::LastDarwinPlatform + 1,
+ static_assert(std::size(EnvVars) == Darwin::LastDarwinPlatform + 1,
"Missing platform");
- for (const auto &I : llvm::enumerate(llvm::makeArrayRef(EnvVars))) {
+ for (const auto &I : llvm::enumerate(llvm::ArrayRef(EnvVars))) {
if (char *Env = ::getenv(I.value()))
Targets[I.index()] = Env;
}
@@ -1649,11 +1924,11 @@ getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver,
Targets[Darwin::TvOS] = "";
} else {
// Don't allow conflicts in any other platform.
- unsigned FirstTarget = llvm::array_lengthof(Targets);
- for (unsigned I = 0; I != llvm::array_lengthof(Targets); ++I) {
+ unsigned FirstTarget = std::size(Targets);
+ for (unsigned I = 0; I != std::size(Targets); ++I) {
if (Targets[I].empty())
continue;
- if (FirstTarget == llvm::array_lengthof(Targets))
+ if (FirstTarget == std::size(Targets))
FirstTarget = I;
else
TheDriver.Diag(diag::err_drv_conflicting_deployment_targets)
@@ -1661,13 +1936,13 @@ getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver,
}
}
- for (const auto &Target : llvm::enumerate(llvm::makeArrayRef(Targets))) {
+ for (const auto &Target : llvm::enumerate(llvm::ArrayRef(Targets))) {
if (!Target.value().empty())
return DarwinPlatform::createDeploymentTargetEnv(
(Darwin::DarwinPlatformKind)Target.index(), EnvVars[Target.index()],
Target.value());
}
- return None;
+ return std::nullopt;
}
/// Returns the SDK name without the optional prefix that ends with a '.' or an
@@ -1682,16 +1957,16 @@ static StringRef dropSDKNamePrefix(StringRef SDKName) {
/// Tries to infer the deployment target from the SDK specified by -isysroot
/// (or SDKROOT). Uses the version specified in the SDKSettings.json file if
/// it's available.
-Optional<DarwinPlatform>
+std::optional<DarwinPlatform>
inferDeploymentTargetFromSDK(DerivedArgList &Args,
- const Optional<DarwinSDKInfo> &SDKInfo) {
+ const std::optional<DarwinSDKInfo> &SDKInfo) {
const Arg *A = Args.getLastArg(options::OPT_isysroot);
if (!A)
- return None;
+ return std::nullopt;
StringRef isysroot = A->getValue();
StringRef SDK = Darwin::getSDKName(isysroot);
if (!SDK.size())
- return None;
+ return std::nullopt;
std::string Version;
if (SDKInfo) {
@@ -1706,26 +1981,33 @@ inferDeploymentTargetFromSDK(DerivedArgList &Args,
Version = std::string(SDK.slice(StartVer, EndVer + 1));
}
if (Version.empty())
- return None;
+ return std::nullopt;
auto CreatePlatformFromSDKName =
- [&](StringRef SDK) -> Optional<DarwinPlatform> {
- if (SDK.startswith("iPhoneOS") || SDK.startswith("iPhoneSimulator"))
+ [&](StringRef SDK) -> std::optional<DarwinPlatform> {
+ if (SDK.starts_with("iPhoneOS") || SDK.starts_with("iPhoneSimulator"))
return DarwinPlatform::createFromSDK(
Darwin::IPhoneOS, Version,
- /*IsSimulator=*/SDK.startswith("iPhoneSimulator"));
- else if (SDK.startswith("MacOSX"))
+ /*IsSimulator=*/SDK.starts_with("iPhoneSimulator"));
+ else if (SDK.starts_with("MacOSX"))
return DarwinPlatform::createFromSDK(Darwin::MacOS,
getSystemOrSDKMacOSVersion(Version));
- else if (SDK.startswith("WatchOS") || SDK.startswith("WatchSimulator"))
+ else if (SDK.starts_with("WatchOS") || SDK.starts_with("WatchSimulator"))
return DarwinPlatform::createFromSDK(
Darwin::WatchOS, Version,
- /*IsSimulator=*/SDK.startswith("WatchSimulator"));
- else if (SDK.startswith("AppleTVOS") || SDK.startswith("AppleTVSimulator"))
+ /*IsSimulator=*/SDK.starts_with("WatchSimulator"));
+ else if (SDK.starts_with("AppleTVOS") ||
+ SDK.starts_with("AppleTVSimulator"))
return DarwinPlatform::createFromSDK(
Darwin::TvOS, Version,
- /*IsSimulator=*/SDK.startswith("AppleTVSimulator"));
- return None;
+ /*IsSimulator=*/SDK.starts_with("AppleTVSimulator"));
+ else if (SDK.starts_with("XR"))
+ return DarwinPlatform::createFromSDK(
+ Darwin::XROS, Version,
+ /*IsSimulator=*/SDK.contains("Simulator"));
+ else if (SDK.starts_with("DriverKit"))
+ return DarwinPlatform::createFromSDK(Darwin::DriverKit, Version);
+ return std::nullopt;
};
if (auto Result = CreatePlatformFromSDKName(SDK))
return Result;
@@ -1735,7 +2017,7 @@ inferDeploymentTargetFromSDK(DerivedArgList &Args,
std::string getOSVersion(llvm::Triple::OSType OS, const llvm::Triple &Triple,
const Driver &TheDriver) {
- unsigned Major, Minor, Micro;
+ VersionTuple OsVersion;
llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
switch (OS) {
case llvm::Triple::Darwin:
@@ -1744,19 +2026,30 @@ std::string getOSVersion(llvm::Triple::OSType OS, const llvm::Triple &Triple,
// macos, use the host triple to infer OS version.
if (Triple.isMacOSX() && SystemTriple.isMacOSX() &&
!Triple.getOSMajorVersion())
- SystemTriple.getMacOSXVersion(Major, Minor, Micro);
- else if (!Triple.getMacOSXVersion(Major, Minor, Micro))
+ SystemTriple.getMacOSXVersion(OsVersion);
+ else if (!Triple.getMacOSXVersion(OsVersion))
TheDriver.Diag(diag::err_drv_invalid_darwin_version)
<< Triple.getOSName();
break;
case llvm::Triple::IOS:
- Triple.getiOSVersion(Major, Minor, Micro);
+ if (Triple.isMacCatalystEnvironment() && !Triple.getOSMajorVersion()) {
+ OsVersion = VersionTuple(13, 1);
+ } else
+ OsVersion = Triple.getiOSVersion();
break;
case llvm::Triple::TvOS:
- Triple.getOSVersion(Major, Minor, Micro);
+ OsVersion = Triple.getOSVersion();
break;
case llvm::Triple::WatchOS:
- Triple.getWatchOSVersion(Major, Minor, Micro);
+ OsVersion = Triple.getWatchOSVersion();
+ break;
+ case llvm::Triple::XROS:
+ OsVersion = Triple.getOSVersion();
+ if (!OsVersion.getMajor())
+ OsVersion = OsVersion.withMajorReplaced(1);
+ break;
+ case llvm::Triple::DriverKit:
+ OsVersion = Triple.getDriverKitVersion();
break;
default:
llvm_unreachable("Unexpected OS type");
@@ -1764,67 +2057,118 @@ std::string getOSVersion(llvm::Triple::OSType OS, const llvm::Triple &Triple,
}
std::string OSVersion;
- llvm::raw_string_ostream(OSVersion) << Major << '.' << Minor << '.' << Micro;
+ llvm::raw_string_ostream(OSVersion)
+ << OsVersion.getMajor() << '.' << OsVersion.getMinor().value_or(0) << '.'
+ << OsVersion.getSubminor().value_or(0);
return OSVersion;
}
/// Tries to infer the target OS from the -arch.
-Optional<DarwinPlatform>
+std::optional<DarwinPlatform>
inferDeploymentTargetFromArch(DerivedArgList &Args, const Darwin &Toolchain,
const llvm::Triple &Triple,
const Driver &TheDriver) {
llvm::Triple::OSType OSTy = llvm::Triple::UnknownOS;
StringRef MachOArchName = Toolchain.getMachOArchName(Args);
- if (MachOArchName == "arm64" || MachOArchName == "arm64e") {
-#if __arm64__
- // A clang running on an Apple Silicon mac defaults
- // to building for mac when building for arm64 rather than
- // defaulting to iOS.
+ if (MachOArchName == "arm64" || MachOArchName == "arm64e")
OSTy = llvm::Triple::MacOSX;
-#else
- OSTy = llvm::Triple::IOS;
-#endif
- } else if (MachOArchName == "armv7" || MachOArchName == "armv7s")
+ else if (MachOArchName == "armv7" || MachOArchName == "armv7s")
OSTy = llvm::Triple::IOS;
else if (MachOArchName == "armv7k" || MachOArchName == "arm64_32")
OSTy = llvm::Triple::WatchOS;
else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
MachOArchName != "armv7em")
OSTy = llvm::Triple::MacOSX;
-
if (OSTy == llvm::Triple::UnknownOS)
- return None;
+ return std::nullopt;
return DarwinPlatform::createFromArch(OSTy,
getOSVersion(OSTy, Triple, TheDriver));
}
/// Returns the deployment target that's specified using the -target option.
-Optional<DarwinPlatform> getDeploymentTargetFromTargetArg(
+std::optional<DarwinPlatform> getDeploymentTargetFromTargetArg(
DerivedArgList &Args, const llvm::Triple &Triple, const Driver &TheDriver,
- const Optional<DarwinSDKInfo> &SDKInfo) {
+ const std::optional<DarwinSDKInfo> &SDKInfo) {
if (!Args.hasArg(options::OPT_target))
- return None;
+ return std::nullopt;
if (Triple.getOS() == llvm::Triple::Darwin ||
Triple.getOS() == llvm::Triple::UnknownOS)
- return None;
+ return std::nullopt;
std::string OSVersion = getOSVersion(Triple.getOS(), Triple, TheDriver);
- return DarwinPlatform::createFromTarget(
- Triple, OSVersion, Args.getLastArg(options::OPT_target), SDKInfo);
+ std::optional<llvm::Triple> TargetVariantTriple;
+ for (const Arg *A : Args.filtered(options::OPT_darwin_target_variant)) {
+ llvm::Triple TVT(A->getValue());
+ // Find a matching <arch>-<vendor> target variant triple that can be used.
+ if ((Triple.getArch() == llvm::Triple::aarch64 ||
+ TVT.getArchName() == Triple.getArchName()) &&
+ TVT.getArch() == Triple.getArch() &&
+ TVT.getSubArch() == Triple.getSubArch() &&
+ TVT.getVendor() == Triple.getVendor()) {
+ if (TargetVariantTriple)
+ continue;
+ A->claim();
+ // Accept a -target-variant triple when compiling code that may run on
+ // macOS or Mac Catalyst.
+ if ((Triple.isMacOSX() && TVT.getOS() == llvm::Triple::IOS &&
+ TVT.isMacCatalystEnvironment()) ||
+ (TVT.isMacOSX() && Triple.getOS() == llvm::Triple::IOS &&
+ Triple.isMacCatalystEnvironment())) {
+ TargetVariantTriple = TVT;
+ continue;
+ }
+ TheDriver.Diag(diag::err_drv_target_variant_invalid)
+ << A->getSpelling() << A->getValue();
+ }
+ }
+ return DarwinPlatform::createFromTarget(Triple, OSVersion,
+ Args.getLastArg(options::OPT_target),
+ TargetVariantTriple, SDKInfo);
}
-Optional<DarwinSDKInfo> parseSDKSettings(llvm::vfs::FileSystem &VFS,
- const ArgList &Args,
- const Driver &TheDriver) {
+/// Returns the deployment target that's specified using the -mtargetos option.
+std::optional<DarwinPlatform> getDeploymentTargetFromMTargetOSArg(
+ DerivedArgList &Args, const Driver &TheDriver,
+ const std::optional<DarwinSDKInfo> &SDKInfo) {
+ auto *A = Args.getLastArg(options::OPT_mtargetos_EQ);
+ if (!A)
+ return std::nullopt;
+ 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:
+ case llvm::Triple::XROS:
+ break;
+ default:
+ TheDriver.Diag(diag::err_drv_invalid_os_in_arg)
+ << TT.getOSName() << A->getAsString(Args);
+ return std::nullopt;
+ }
+
+ VersionTuple Version = TT.getOSVersion();
+ if (!Version.getMajor()) {
+ TheDriver.Diag(diag::err_drv_invalid_version_number)
+ << A->getAsString(Args);
+ return std::nullopt;
+ }
+ return DarwinPlatform::createFromMTargetOS(TT.getOS(), Version,
+ TT.getEnvironment(), A, SDKInfo);
+}
+
+std::optional<DarwinSDKInfo> parseSDKSettings(llvm::vfs::FileSystem &VFS,
+ const ArgList &Args,
+ const Driver &TheDriver) {
const Arg *A = Args.getLastArg(options::OPT_isysroot);
if (!A)
- return None;
+ return std::nullopt;
StringRef isysroot = A->getValue();
auto SDKInfoOrErr = parseDarwinSDKInfo(VFS, isysroot);
if (!SDKInfoOrErr) {
llvm::consumeError(SDKInfoOrErr.takeError());
TheDriver.Diag(diag::warn_drv_darwin_sdk_invalid_settings);
- return None;
+ return std::nullopt;
}
return *SDKInfoOrErr;
}
@@ -1858,10 +2202,17 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
SDKInfo = parseSDKSettings(getVFS(), Args, getDriver());
// The OS and the version can be specified using the -target argument.
- Optional<DarwinPlatform> OSTarget =
+ std::optional<DarwinPlatform> OSTarget =
getDeploymentTargetFromTargetArg(Args, getTriple(), getDriver(), SDKInfo);
if (OSTarget) {
- Optional<DarwinPlatform> OSVersionArgTarget =
+ // 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;
+ }
+ std::optional<DarwinPlatform> OSVersionArgTarget =
getDeploymentTargetFromOSVersionArg(Args, getDriver());
if (OSVersionArgTarget) {
unsigned TargetMajor, TargetMinor, TargetMicro;
@@ -1887,11 +2238,23 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
std::string OSVersionArg =
OSVersionArgTarget->getAsString(Args, Opts);
std::string TargetArg = OSTarget->getAsString(Args, Opts);
- getDriver().Diag(clang::diag::warn_drv_overriding_flag_option)
+ getDriver().Diag(clang::diag::warn_drv_overriding_option)
<< OSVersionArg << TargetArg;
}
}
}
+ } 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=.
+ std::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());
@@ -1902,7 +2265,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
getDeploymentTargetFromEnvironmentVariables(getDriver(), getTriple());
if (OSTarget) {
// Don't infer simulator from the arch when the SDK is also specified.
- Optional<DarwinPlatform> SDKTarget =
+ std::optional<DarwinPlatform> SDKTarget =
inferDeploymentTargetFromSDK(Args, SDKInfo);
if (SDKTarget)
OSTarget->setEnvironment(SDKTarget->getEnvironment());
@@ -1931,17 +2294,20 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
unsigned Major, Minor, Micro;
bool HadExtra;
+ // The major version should not be over this number.
+ const unsigned MajorVersionLimit = 1000;
// Set the tool chain target information.
if (Platform == MacOS) {
if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
Micro, HadExtra) ||
- HadExtra || Major < 10 || Major >= 100 || Minor >= 100 || Micro >= 100)
+ HadExtra || Major < 10 || Major >= MajorVersionLimit || Minor >= 100 ||
+ Micro >= 100)
getDriver().Diag(diag::err_drv_invalid_version_number)
<< OSTarget->getAsString(Args, Opts);
} else if (Platform == IPhoneOS) {
if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
Micro, HadExtra) ||
- HadExtra || Major >= 100 || Minor >= 100 || Micro >= 100)
+ HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
getDriver().Diag(diag::err_drv_invalid_version_number)
<< OSTarget->getAsString(Args, Opts);
;
@@ -1973,13 +2339,27 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
} else if (Platform == TvOS) {
if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
Micro, HadExtra) ||
- HadExtra || Major >= 100 || Minor >= 100 || Micro >= 100)
+ HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
getDriver().Diag(diag::err_drv_invalid_version_number)
<< OSTarget->getAsString(Args, Opts);
} else if (Platform == WatchOS) {
if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
Micro, HadExtra) ||
- HadExtra || Major >= 10 || Minor >= 100 || Micro >= 100)
+ HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)
+ getDriver().Diag(diag::err_drv_invalid_version_number)
+ << OSTarget->getAsString(Args, Opts);
+ } else if (Platform == DriverKit) {
+ if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
+ Micro, HadExtra) ||
+ HadExtra || Major < 19 || Major >= MajorVersionLimit || Minor >= 100 ||
+ Micro >= 100)
+ getDriver().Diag(diag::err_drv_invalid_version_number)
+ << OSTarget->getAsString(Args, Opts);
+ } else if (Platform == XROS) {
+ if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
+ Micro, HadExtra) ||
+ HadExtra || Major < 1 || Major >= MajorVersionLimit || Minor >= 100 ||
+ Micro >= 100)
getDriver().Diag(diag::err_drv_invalid_version_number)
<< OSTarget->getAsString(Args, Opts);
} else
@@ -1988,42 +2368,60 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
DarwinEnvironmentKind Environment = OSTarget->getEnvironment();
// Recognize iOS targets with an x86 architecture as the iOS simulator.
if (Environment == NativeEnvironment && Platform != MacOS &&
- OSTarget->canInferSimulatorFromArch() && getTriple().isX86())
+ Platform != DriverKit && OSTarget->canInferSimulatorFromArch() &&
+ getTriple().isX86())
Environment = Simulator;
VersionTuple NativeTargetVersion;
if (Environment == MacCatalyst)
NativeTargetVersion = OSTarget->getNativeTargetVersion();
setTarget(Platform, Environment, Major, Minor, Micro, NativeTargetVersion);
+ TargetVariantTriple = OSTarget->getTargetVariantTriple();
if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
StringRef SDK = getSDKName(A->getValue());
if (SDK.size() > 0) {
size_t StartVer = SDK.find_first_of("0123456789");
StringRef SDKName = SDK.slice(0, StartVer);
- if (!SDKName.startswith(getPlatformFamily()) &&
- !dropSDKNamePrefix(SDKName).startswith(getPlatformFamily()))
+ if (!SDKName.starts_with(getPlatformFamily()) &&
+ !dropSDKNamePrefix(SDKName).starts_with(getPlatformFamily()))
getDriver().Diag(diag::warn_incompatible_sysroot)
<< SDKName << getPlatformFamily();
}
}
}
-// Returns the effective header sysroot path to use. This comes either from
-// -isysroot or --sysroot.
-llvm::StringRef DarwinClang::GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const {
- if(DriverArgs.hasArg(options::OPT_isysroot))
- return DriverArgs.getLastArgValue(options::OPT_isysroot);
- if (!getDriver().SysRoot.empty())
- return getDriver().SysRoot;
- return "/";
+// For certain platforms/environments almost all resources (e.g., headers) are
+// located in sub-directories, e.g., for DriverKit they live in
+// <SYSROOT>/System/DriverKit/usr/include (instead of <SYSROOT>/usr/include).
+static void AppendPlatformPrefix(SmallString<128> &Path,
+ const llvm::Triple &T) {
+ if (T.isDriverKit()) {
+ llvm::sys::path::append(Path, "System", "DriverKit");
+ }
+}
+
+// Returns the effective sysroot from either -isysroot or --sysroot, plus the
+// platform prefix (if any).
+llvm::SmallString<128>
+DarwinClang::GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const {
+ llvm::SmallString<128> Path("/");
+ if (DriverArgs.hasArg(options::OPT_isysroot))
+ Path = DriverArgs.getLastArgValue(options::OPT_isysroot);
+ else if (!getDriver().SysRoot.empty())
+ Path = getDriver().SysRoot;
+
+ if (hasEffectiveTriple()) {
+ AppendPlatformPrefix(Path, getEffectiveTriple());
+ }
+ return Path;
}
void DarwinClang::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
const Driver &D = getDriver();
- llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs);
+ llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);
bool NoStdInc = DriverArgs.hasArg(options::OPT_nostdinc);
bool NoStdlibInc = DriverArgs.hasArg(options::OPT_nostdlibinc);
@@ -2108,22 +2506,27 @@ void DarwinClang::AddClangCXXStdlibIncludeArgs(
// Also check whether this is used for setting library search paths.
ToolChain::AddClangCXXStdlibIncludeArgs(DriverArgs, CC1Args);
- if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
- DriverArgs.hasArg(options::OPT_nostdincxx))
+ if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc,
+ options::OPT_nostdincxx))
return;
- llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs);
+ llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);
switch (GetCXXStdlibType(DriverArgs)) {
case ToolChain::CST_Libcxx: {
- // On Darwin, libc++ can be installed in one of the following two places:
- // 1. Alongside the compiler in <install>/include/c++/v1
- // 2. In a SDK (or a custom sysroot) in <sysroot>/usr/include/c++/v1
+ // On Darwin, libc++ can be installed in one of the following places:
+ // 1. Alongside the compiler in <install>/include/c++/v1
+ // 2. Alongside the compiler in <clang-executable-folder>/../include/c++/v1
+ // 3. In a SDK (or a custom sysroot) in <sysroot>/usr/include/c++/v1
//
- // The precendence of paths is as listed above, i.e. we take the first path
- // that exists. Also note that we never include libc++ twice -- we take the
- // first path that exists and don't send the other paths to CC1 (otherwise
+ // The precedence of paths is as listed above, i.e. we take the first path
+ // that exists. Note that we never include libc++ twice -- we take the first
+ // path that exists and don't send the other paths to CC1 (otherwise
// include_next could break).
+ //
+ // Also note that in most cases, (1) and (2) are exactly the same path.
+ // Those two paths will differ only when the `clang` program being run
+ // is actually a symlink to the real executable.
// Check for (1)
// Get from '<install>/bin' to '<install>/include/c++/v1'.
@@ -2140,7 +2543,20 @@ void DarwinClang::AddClangCXXStdlibIncludeArgs(
<< "\"\n";
}
- // Otherwise, check for (2)
+ // (2) Check for the folder where the executable is located, if different.
+ if (getDriver().getInstalledDir() != getDriver().Dir) {
+ InstallBin = llvm::StringRef(getDriver().Dir);
+ llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1");
+ if (getVFS().exists(InstallBin)) {
+ addSystemInclude(DriverArgs, CC1Args, InstallBin);
+ return;
+ } else if (DriverArgs.hasArg(options::OPT_v)) {
+ llvm::errs() << "ignoring nonexistent directory \"" << InstallBin
+ << "\"\n";
+ }
+ }
+
+ // Otherwise, check for (3)
llvm::SmallString<128> SysrootUsr = Sysroot;
llvm::sys::path::append(SysrootUsr, "usr", "include", "c++", "v1");
if (getVFS().exists(SysrootUsr)) {
@@ -2164,17 +2580,6 @@ void DarwinClang::AddClangCXXStdlibIncludeArgs(
switch (arch) {
default: break;
- case llvm::Triple::ppc:
- case llvm::Triple::ppc64:
- IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
- "4.2.1",
- "powerpc-apple-darwin10",
- arch == llvm::Triple::ppc64 ? "ppc64" : "");
- IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
- "4.0.0", "powerpc-apple-darwin10",
- arch == llvm::Triple::ppc64 ? "ppc64" : "");
- break;
-
case llvm::Triple::x86:
case llvm::Triple::x86_64:
IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
@@ -2213,6 +2618,7 @@ void DarwinClang::AddClangCXXStdlibIncludeArgs(
break;
}
}
+
void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
CXXStdlibType Type = GetCXXStdlibType(Args);
@@ -2220,6 +2626,8 @@ void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
switch (Type) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
break;
case ToolChain::CST_Libstdcxx:
@@ -2274,6 +2682,12 @@ void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
llvm::sys::path::append(P, "libclang_rt.cc_kext_tvos.a");
} else if (isTargetIPhoneOS()) {
llvm::sys::path::append(P, "libclang_rt.cc_kext_ios.a");
+ } else if (isTargetDriverKit()) {
+ // DriverKit doesn't want extra runtime support.
+ } else if (isTargetXROSDevice()) {
+ llvm::sys::path::append(
+ P, llvm::Twine("libclang_rt.cc_kext_") +
+ llvm::Triple::getOSTypeName(llvm::Triple::XROS) + ".a");
} else {
llvm::sys::path::append(P, "libclang_rt.cc_kext.a");
}
@@ -2301,12 +2715,9 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
if (A->getOption().matches(options::OPT_Xarch__)) {
// Skip this argument unless the architecture matches either the toolchain
// triple arch, or the arch being bound.
- llvm::Triple::ArchType XarchArch =
- tools::darwin::getArchTypeForMachOArchName(A->getValue(0));
- if (!(XarchArch == getArch() ||
- (!BoundArch.empty() &&
- XarchArch ==
- tools::darwin::getArchTypeForMachOArchName(BoundArch))))
+ StringRef XarchArch = A->getValue(0);
+ if (!(XarchArch == getArchName() ||
+ (!BoundArch.empty() && XarchArch == BoundArch)))
continue;
Arg *OriginalArg = A;
@@ -2376,19 +2787,11 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
DAL->AddFlagArg(
A, Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings));
break;
-
- case options::OPT_fpascal_strings:
- DAL->AddFlagArg(A, Opts.getOption(options::OPT_mpascal_strings));
- break;
-
- case options::OPT_fno_pascal_strings:
- DAL->AddFlagArg(A, Opts.getOption(options::OPT_mno_pascal_strings));
- break;
}
}
// Add the arch options based on the particular spelling of -arch, to match
- // how the driver driver works.
+ // how the driver works.
if (!BoundArch.empty()) {
StringRef Name = BoundArch;
const Option MCpu = Opts.getOption(options::OPT_mcpu_EQ);
@@ -2499,11 +2902,36 @@ bool Darwin::isAlignedAllocationUnavailable() const {
case WatchOS: // Earlier than 4.0.
OS = llvm::Triple::WatchOS;
break;
+ case XROS: // Always available.
+ return false;
+ case DriverKit: // Always available.
+ return false;
}
return TargetVersion < alignedAllocMinVersion(OS);
}
+static bool sdkSupportsBuiltinModules(const Darwin::DarwinPlatformKind &TargetPlatform, const std::optional<DarwinSDKInfo> &SDKInfo) {
+ if (!SDKInfo)
+ return false;
+
+ VersionTuple SDKVersion = SDKInfo->getVersion();
+ switch (TargetPlatform) {
+ case Darwin::MacOS:
+ return SDKVersion >= VersionTuple(99U);
+ case Darwin::IPhoneOS:
+ return SDKVersion >= VersionTuple(99U);
+ case Darwin::TvOS:
+ return SDKVersion >= VersionTuple(99U);
+ case Darwin::WatchOS:
+ return SDKVersion >= VersionTuple(99U);
+ case Darwin::XROS:
+ return SDKVersion >= VersionTuple(99U);
+ default:
+ return true;
+ }
+}
+
void Darwin::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadKind) const {
@@ -2514,6 +2942,45 @@ void Darwin::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
isAlignedAllocationUnavailable())
CC1Args.push_back("-faligned-alloc-unavailable");
+ addClangCC1ASTargetOptions(DriverArgs, CC1Args);
+
+ // Enable compatibility mode for NSItemProviderCompletionHandler in
+ // Foundation/NSItemProvider.h.
+ CC1Args.push_back("-fcompatibility-qualified-id-block-type-checking");
+
+ // Give static local variables in inline functions hidden visibility when
+ // -fvisibility-inlines-hidden is enabled.
+ if (!DriverArgs.getLastArgNoClaim(
+ options::OPT_fvisibility_inlines_hidden_static_local_var,
+ options::OPT_fno_visibility_inlines_hidden_static_local_var))
+ CC1Args.push_back("-fvisibility-inlines-hidden-static-local-var");
+
+ // Earlier versions of the darwin SDK have the C standard library headers
+ // all together in the Darwin module. That leads to module cycles with
+ // the _Builtin_ modules. e.g. <inttypes.h> on darwin includes <stdint.h>.
+ // The builtin <stdint.h> include-nexts <stdint.h>. When both of those
+ // darwin headers are in the Darwin module, there's a module cycle Darwin ->
+ // _Builtin_stdint -> Darwin (i.e. inttypes.h (darwin) -> stdint.h (builtin) ->
+ // stdint.h (darwin)). This is fixed in later versions of the darwin SDK,
+ // but until then, the builtin headers need to join the system modules.
+ // i.e. when the builtin stdint.h is in the Darwin module too, the cycle
+ // goes away. Note that -fbuiltin-headers-in-system-modules does nothing
+ // to fix the same problem with C++ headers, and is generally fragile.
+ if (!sdkSupportsBuiltinModules(TargetPlatform, SDKInfo))
+ CC1Args.push_back("-fbuiltin-headers-in-system-modules");
+
+ if (!DriverArgs.hasArgNoClaim(options::OPT_fdefine_target_os_macros,
+ options::OPT_fno_define_target_os_macros))
+ CC1Args.push_back("-fdefine-target-os-macros");
+}
+
+void Darwin::addClangCC1ASTargetOptions(
+ const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CC1ASArgs) const {
+ if (TargetVariantTriple) {
+ CC1ASArgs.push_back("-darwin-target-variant-triple");
+ CC1ASArgs.push_back(Args.MakeArgString(TargetVariantTriple->getTriple()));
+ }
+
if (SDKInfo) {
/// Pass the SDK version to the compiler when the SDK information is
/// available.
@@ -2521,32 +2988,45 @@ void Darwin::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
std::string Arg;
llvm::raw_string_ostream OS(Arg);
OS << "-target-sdk-version=" << V;
- CC1Args.push_back(DriverArgs.MakeArgString(OS.str()));
+ CC1ASArgs.push_back(Args.MakeArgString(OS.str()));
};
if (isTargetMacCatalyst()) {
if (const auto *MacOStoMacCatalystMapping = SDKInfo->getVersionMapping(
DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
- Optional<VersionTuple> SDKVersion = MacOStoMacCatalystMapping->map(
- SDKInfo->getVersion(), minimumMacCatalystDeploymentTarget(), None);
+ std::optional<VersionTuple> SDKVersion = MacOStoMacCatalystMapping->map(
+ SDKInfo->getVersion(), minimumMacCatalystDeploymentTarget(),
+ std::nullopt);
EmitTargetSDKVersionArg(
SDKVersion ? *SDKVersion : minimumMacCatalystDeploymentTarget());
}
} else {
EmitTargetSDKVersionArg(SDKInfo->getVersion());
}
- }
-
- // Enable compatibility mode for NSItemProviderCompletionHandler in
- // Foundation/NSItemProvider.h.
- CC1Args.push_back("-fcompatibility-qualified-id-block-type-checking");
- // Give static local variables in inline functions hidden visibility when
- // -fvisibility-inlines-hidden is enabled.
- if (!DriverArgs.getLastArgNoClaim(
- options::OPT_fvisibility_inlines_hidden_static_local_var,
- options::OPT_fno_visibility_inlines_hidden_static_local_var))
- CC1Args.push_back("-fvisibility-inlines-hidden-static-local-var");
+ /// Pass the target variant SDK version to the compiler when the SDK
+ /// information is available and is required for target variant.
+ if (TargetVariantTriple) {
+ if (isTargetMacCatalyst()) {
+ std::string Arg;
+ llvm::raw_string_ostream OS(Arg);
+ OS << "-darwin-target-variant-sdk-version=" << SDKInfo->getVersion();
+ CC1ASArgs.push_back(Args.MakeArgString(OS.str()));
+ } else if (const auto *MacOStoMacCatalystMapping =
+ SDKInfo->getVersionMapping(
+ DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
+ if (std::optional<VersionTuple> SDKVersion =
+ MacOStoMacCatalystMapping->map(
+ SDKInfo->getVersion(), minimumMacCatalystDeploymentTarget(),
+ std::nullopt)) {
+ std::string Arg;
+ llvm::raw_string_ostream OS(Arg);
+ OS << "-darwin-target-variant-sdk-version=" << *SDKVersion;
+ CC1ASArgs.push_back(Args.MakeArgString(OS.str()));
+ }
+ }
+ }
+ }
}
DerivedArgList *
@@ -2555,7 +3035,6 @@ Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
// First get the generic Apple args, before moving onto Darwin-specific ones.
DerivedArgList *DAL =
MachO::TranslateArgs(Args, BoundArch, DeviceOffloadKind);
- const OptTable &Opts = getDriver().getOpts();
// If no architecture is bound, none of the translations here are relevant.
if (BoundArch.empty())
@@ -2570,7 +3049,7 @@ Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
// FIXME: It would be far better to avoid inserting those -static arguments,
// but we can't check the deployment target in the translation code until
// it is set here.
- if (isTargetWatchOSBased() ||
+ if (isTargetWatchOSBased() || isTargetDriverKit() || isTargetXROS() ||
(isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0))) {
for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) {
Arg *A = *it;
@@ -2587,26 +3066,6 @@ Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
}
}
- if (!Args.getLastArg(options::OPT_stdlib_EQ) &&
- GetCXXStdlibType(Args) == ToolChain::CST_Libcxx)
- DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_stdlib_EQ),
- "libc++");
-
- // Validate the C++ standard library choice.
- CXXStdlibType Type = GetCXXStdlibType(*DAL);
- if (Type == ToolChain::CST_Libcxx) {
- // Check whether the target provides libc++.
- StringRef where;
-
- // Complain about targeting iOS < 5.0 in any way.
- if (isTargetIOSBased() && isIPhoneOSVersionLT(5, 0))
- where = "iOS 5.0";
-
- if (where != StringRef()) {
- getDriver().Diag(clang::diag::err_drv_invalid_libcxx_deployment) << where;
- }
- }
-
auto Arch = tools::darwin::getArchTypeForMachOArchName(BoundArch);
if ((Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb)) {
if (Args.hasFlag(options::OPT_fomit_frame_pointer,
@@ -2618,13 +3077,19 @@ Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
return DAL;
}
-bool MachO::IsUnwindTablesDefault(const ArgList &Args) const {
+ToolChain::UnwindTableLevel MachO::getDefaultUnwindTableLevel(const ArgList &Args) const {
// Unwind tables are not emitted if -fno-exceptions is supplied (except when
// targeting x86_64).
- return getArch() == llvm::Triple::x86_64 ||
- (GetExceptionModel(Args) != llvm::ExceptionHandling::SjLj &&
- Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,
- true));
+ if (getArch() == llvm::Triple::x86_64 ||
+ (GetExceptionModel(Args) != llvm::ExceptionHandling::SjLj &&
+ Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,
+ true)))
+ return (getArch() == llvm::Triple::aarch64 ||
+ getArch() == llvm::Triple::aarch64_32)
+ ? UnwindTableLevel::Synchronous
+ : UnwindTableLevel::Asynchronous;
+
+ return UnwindTableLevel::None;
}
bool MachO::UseDwarfDebugFlags() const {
@@ -2633,6 +3098,12 @@ bool MachO::UseDwarfDebugFlags() const {
return false;
}
+std::string MachO::GetGlobalDebugPathRemapping() const {
+ if (const char *S = ::getenv("RC_DEBUG_PREFIX_MAP"))
+ return S;
+ return {};
+}
+
llvm::ExceptionHandling Darwin::GetExceptionModel(const ArgList &Args) const {
// Darwin uses SjLj exceptions on ARM.
if (getTriple().getArch() != llvm::Triple::arm &&
@@ -2656,7 +3127,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 ||
@@ -2672,6 +3143,8 @@ void Darwin::addMinVersionArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
VersionTuple TargetVersion = getTripleTargetVersion();
+ assert(!isTargetXROS() && "xrOS always uses -platform-version");
+
if (isTargetWatchOS())
CmdArgs.push_back("-watchos_version_min");
else if (isTargetWatchOSSimulator())
@@ -2680,6 +3153,8 @@ void Darwin::addMinVersionArgs(const ArgList &Args,
CmdArgs.push_back("-tvos_version_min");
else if (isTargetTvOSSimulator())
CmdArgs.push_back("-tvos_simulator_version_min");
+ else if (isTargetDriverKit())
+ CmdArgs.push_back("-driverkit_version_min");
else if (isTargetIOSSimulator())
CmdArgs.push_back("-ios_simulator_version_min");
else if (isTargetIOSBased())
@@ -2695,6 +3170,25 @@ void Darwin::addMinVersionArgs(const ArgList &Args,
if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
TargetVersion = MinTgtVers;
CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
+ if (TargetVariantTriple) {
+ assert(isTargetMacOSBased() && "unexpected target");
+ VersionTuple VariantTargetVersion;
+ if (TargetVariantTriple->isMacOSX()) {
+ CmdArgs.push_back("-macosx_version_min");
+ TargetVariantTriple->getMacOSXVersion(VariantTargetVersion);
+ } else {
+ assert(TargetVariantTriple->isiOS() &&
+ TargetVariantTriple->isMacCatalystEnvironment() &&
+ "unexpected target variant triple");
+ CmdArgs.push_back("-maccatalyst_version_min");
+ VariantTargetVersion = TargetVariantTriple->getiOSVersion();
+ }
+ VersionTuple MinTgtVers =
+ TargetVariantTriple->getMinimumSupportedOSVersion();
+ if (MinTgtVers.getMajor() && MinTgtVers > VariantTargetVersion)
+ VariantTargetVersion = MinTgtVers;
+ CmdArgs.push_back(Args.MakeArgString(VariantTargetVersion.getAsString()));
+ }
}
static const char *getPlatformName(Darwin::DarwinPlatformKind Platform,
@@ -2710,58 +3204,100 @@ static const char *getPlatformName(Darwin::DarwinPlatformKind Platform,
return "tvos";
case Darwin::WatchOS:
return "watchos";
+ case Darwin::XROS:
+ return "xros";
+ case Darwin::DriverKit:
+ return "driverkit";
}
llvm_unreachable("invalid platform");
}
void Darwin::addPlatformVersionArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const {
- // -platform_version <platform> <target_version> <sdk_version>
- // Both the target and SDK version support only up to 3 components.
- CmdArgs.push_back("-platform_version");
- std::string PlatformName = getPlatformName(TargetPlatform, TargetEnvironment);
- if (TargetEnvironment == Darwin::Simulator)
- PlatformName += "-simulator";
- CmdArgs.push_back(Args.MakeArgString(PlatformName));
- VersionTuple TargetVersion = getTripleTargetVersion().withoutBuild();
- VersionTuple MinTgtVers = getEffectiveTriple().getMinimumSupportedOSVersion();
- if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
- TargetVersion = MinTgtVers;
- CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
+ auto EmitPlatformVersionArg =
+ [&](const VersionTuple &TV, Darwin::DarwinPlatformKind TargetPlatform,
+ Darwin::DarwinEnvironmentKind TargetEnvironment,
+ const llvm::Triple &TT) {
+ // -platform_version <platform> <target_version> <sdk_version>
+ // Both the target and SDK version support only up to 3 components.
+ CmdArgs.push_back("-platform_version");
+ std::string PlatformName =
+ getPlatformName(TargetPlatform, TargetEnvironment);
+ if (TargetEnvironment == Darwin::Simulator)
+ PlatformName += "-simulator";
+ CmdArgs.push_back(Args.MakeArgString(PlatformName));
+ VersionTuple TargetVersion = TV.withoutBuild();
+ if ((TargetPlatform == Darwin::IPhoneOS ||
+ TargetPlatform == Darwin::TvOS) &&
+ getTriple().getArchName() == "arm64e" &&
+ TargetVersion.getMajor() < 14) {
+ // arm64e slice is supported on iOS/tvOS 14+ only.
+ TargetVersion = VersionTuple(14, 0);
+ }
+ VersionTuple MinTgtVers = TT.getMinimumSupportedOSVersion();
+ if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
+ TargetVersion = MinTgtVers;
+ CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
+
+ if (TargetPlatform == IPhoneOS && TargetEnvironment == MacCatalyst) {
+ // Mac Catalyst programs must use the appropriate iOS SDK version
+ // that corresponds to the macOS SDK version used for the compilation.
+ std::optional<VersionTuple> iOSSDKVersion;
+ if (SDKInfo) {
+ if (const auto *MacOStoMacCatalystMapping =
+ SDKInfo->getVersionMapping(
+ DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
+ iOSSDKVersion = MacOStoMacCatalystMapping->map(
+ SDKInfo->getVersion().withoutBuild(),
+ minimumMacCatalystDeploymentTarget(), std::nullopt);
+ }
+ }
+ CmdArgs.push_back(Args.MakeArgString(
+ (iOSSDKVersion ? *iOSSDKVersion
+ : minimumMacCatalystDeploymentTarget())
+ .getAsString()));
+ return;
+ }
- if (isTargetMacCatalyst()) {
- // Mac Catalyst programs must use the appropriate iOS SDK version
- // that corresponds to the macOS SDK version used for the compilation.
- Optional<VersionTuple> iOSSDKVersion;
- if (SDKInfo) {
- if (const auto *MacOStoMacCatalystMapping = SDKInfo->getVersionMapping(
- DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
- iOSSDKVersion = MacOStoMacCatalystMapping->map(
- SDKInfo->getVersion().withoutBuild(),
- minimumMacCatalystDeploymentTarget(), None);
- }
- }
- CmdArgs.push_back(Args.MakeArgString(
- (iOSSDKVersion ? *iOSSDKVersion : minimumMacCatalystDeploymentTarget())
- .getAsString()));
+ if (SDKInfo) {
+ VersionTuple SDKVersion = SDKInfo->getVersion().withoutBuild();
+ if (!SDKVersion.getMinor())
+ SDKVersion = VersionTuple(SDKVersion.getMajor(), 0);
+ CmdArgs.push_back(Args.MakeArgString(SDKVersion.getAsString()));
+ } else {
+ // Use an SDK version that's matching the deployment target if the SDK
+ // version is missing. This is preferred over an empty SDK version
+ // (0.0.0) as the system's runtime might expect the linked binary to
+ // contain a valid SDK version in order for the binary to work
+ // correctly. It's reasonable to use the deployment target version as
+ // a proxy for the SDK version because older SDKs don't guarantee
+ // support for deployment targets newer than the SDK versions, so that
+ // rules out using some predetermined older SDK version, which leaves
+ // the deployment target version as the only reasonable choice.
+ CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
+ }
+ };
+ EmitPlatformVersionArg(getTripleTargetVersion(), TargetPlatform,
+ TargetEnvironment, getEffectiveTriple());
+ if (!TargetVariantTriple)
return;
- }
-
- if (SDKInfo) {
- VersionTuple SDKVersion = SDKInfo->getVersion().withoutBuild();
- CmdArgs.push_back(Args.MakeArgString(SDKVersion.getAsString()));
+ Darwin::DarwinPlatformKind Platform;
+ Darwin::DarwinEnvironmentKind Environment;
+ VersionTuple TargetVariantVersion;
+ if (TargetVariantTriple->isMacOSX()) {
+ TargetVariantTriple->getMacOSXVersion(TargetVariantVersion);
+ Platform = Darwin::MacOS;
+ Environment = Darwin::NativeEnvironment;
} else {
- // Use an SDK version that's matching the deployment target if the SDK
- // version is missing. This is preferred over an empty SDK version (0.0.0)
- // as the system's runtime might expect the linked binary to contain a
- // valid SDK version in order for the binary to work correctly. It's
- // reasonable to use the deployment target version as a proxy for the
- // SDK version because older SDKs don't guarantee support for deployment
- // targets newer than the SDK versions, so that rules out using some
- // predetermined older SDK version, which leaves the deployment target
- // version as the only reasonable choice.
- CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
+ assert(TargetVariantTriple->isiOS() &&
+ TargetVariantTriple->isMacCatalystEnvironment() &&
+ "unexpected target variant triple");
+ TargetVariantVersion = TargetVariantTriple->getiOSVersion();
+ Platform = Darwin::IPhoneOS;
+ Environment = Darwin::MacCatalyst;
}
+ EmitPlatformVersionArg(TargetVariantVersion, Platform, Environment,
+ *TargetVariantTriple);
}
// Add additional link args for the -dynamiclib option.
@@ -2866,7 +3402,7 @@ void Darwin::addStartObjectFileArgs(const ArgList &Args,
}
void Darwin::CheckObjCARC() const {
- if (isTargetIOSBased() || isTargetWatchOSBased() ||
+ if (isTargetIOSBased() || isTargetWatchOSBased() || isTargetXROS() ||
(isTargetMacOSBased() && !isMacosxVersionLT(10, 6)))
return;
getDriver().Diag(diag::err_arc_unsupported_on_toolchain);
@@ -2882,7 +3418,6 @@ SanitizerMask Darwin::getSupportedSanitizers() const {
Res |= SanitizerKind::Leak;
Res |= SanitizerKind::Fuzzer;
Res |= SanitizerKind::FuzzerNoLink;
- Res |= SanitizerKind::Function;
Res |= SanitizerKind::ObjCCast;
// Prior to 10.9, macOS shipped a version of the C++ standard library without
@@ -2892,16 +3427,15 @@ SanitizerMask Darwin::getSupportedSanitizers() const {
!(isTargetIPhoneOS() && isIPhoneOSVersionLT(5, 0)))
Res |= SanitizerKind::Vptr;
- if ((IsX86_64 || IsAArch64) && isTargetMacOSBased()) {
+ if ((IsX86_64 || IsAArch64) &&
+ (isTargetMacOSBased() || isTargetIOSSimulator() ||
+ isTargetTvOSSimulator() || isTargetWatchOSSimulator())) {
Res |= SanitizerKind::Thread;
- } else if (isTargetIOSSimulator() || isTargetTvOSSimulator()) {
- if (IsX86_64)
- Res |= SanitizerKind::Thread;
}
return Res;
}
void Darwin::printVerboseInfo(raw_ostream &OS) const {
- CudaInstallation.print(OS);
- RocmInstallation.print(OS);
+ CudaInstallation->print(OS);
+ RocmInstallation->print(OS);
}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Darwin.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Darwin.h
index 4de122c8d513..5e60b0841d6d 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Darwin.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Darwin.h
@@ -10,6 +10,7 @@
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H
#include "Cuda.h"
+#include "LazyDetector.h"
#include "ROCm.h"
#include "clang/Basic/DarwinSDKInfo.h"
#include "clang/Basic/LangOptions.h"
@@ -28,7 +29,8 @@ namespace tools {
namespace darwin {
llvm::Triple::ArchType getArchTypeForMachOArchName(StringRef Str);
-void setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str);
+void setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str,
+ const llvm::opt::ArgList &Args);
class LLVM_LIBRARY_VISIBILITY MachOTool : public Tool {
virtual void anchor();
@@ -63,8 +65,8 @@ class LLVM_LIBRARY_VISIBILITY Linker : public MachOTool {
bool NeedsTempPath(const InputInfoList &Inputs) const;
void AddLinkArgs(Compilation &C, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
- const InputInfoList &Inputs, unsigned Version[5],
- bool LinkerIsLLD, bool LinkerIsLLDDarwinNew) const;
+ const InputInfoList &Inputs, VersionTuple Version,
+ bool LinkerIsLLD, bool UsePlatformVersion) const;
public:
Linker(const ToolChain &TC) : MachOTool("darwin::Linker", "linker", TC) {}
@@ -78,6 +80,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 +141,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:
@@ -132,6 +149,9 @@ private:
mutable std::unique_ptr<tools::darwin::Dsymutil> Dsymutil;
mutable std::unique_ptr<tools::darwin::VerifyDebug> VerifyDebug;
+ /// The version of the linker known to be available in the tool chain.
+ mutable std::optional<VersionTuple> LinkerVersion;
+
public:
MachO(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
@@ -144,6 +164,10 @@ public:
/// example, Apple treats different ARM variations as distinct architectures.
StringRef getMachOArchName(const llvm::opt::ArgList &Args) const;
+ /// Get the version of the linker known to be available for a particular
+ /// compiler invocation (via the `-mlinker-version=` arg).
+ VersionTuple getLinkerVersion(const llvm::opt::ArgList &Args) const;
+
/// Add the linker arguments to link the ARC runtime library.
virtual void AddLinkARCArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const {}
@@ -216,10 +240,6 @@ public:
// expected to use /usr/include/Block.h.
return true;
}
- bool IsIntegratedAssemblerDefault() const override {
- // Default integrated assembler to on for Apple's MachO targets.
- return true;
- }
bool IsMathErrnoDefault() const override { return false; }
@@ -232,19 +252,21 @@ public:
bool UseObjCMixedDispatch() const override { return true; }
- bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override;
+ UnwindTableLevel
+ getDefaultUnwindTableLevel(const llvm::opt::ArgList &Args) const override;
RuntimeLibType GetDefaultRuntimeLibType() const override {
return ToolChain::RLT_CompilerRT;
}
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 UseDwarfDebugFlags() const override;
+ std::string GetGlobalDebugPathRemapping() const override;
llvm::ExceptionHandling
GetExceptionModel(const llvm::opt::ArgList &Args) const override {
@@ -276,7 +298,9 @@ public:
IPhoneOS,
TvOS,
WatchOS,
- LastDarwinPlatform = WatchOS
+ DriverKit,
+ XROS,
+ LastDarwinPlatform = DriverKit
};
enum DarwinEnvironmentKind {
NativeEnvironment,
@@ -293,10 +317,13 @@ public:
mutable VersionTuple OSTargetVersion;
/// The information about the darwin SDK that was used.
- mutable Optional<DarwinSDKInfo> SDKInfo;
+ mutable std::optional<DarwinSDKInfo> SDKInfo;
+
+ /// The target variant triple that was specified (if any).
+ mutable std::optional<llvm::Triple> TargetVariantTriple;
- CudaInstallationDetector CudaInstallation;
- RocmInstallationDetector RocmInstallation;
+ LazyDetector<CudaInstallationDetector> CudaInstallation;
+ LazyDetector<RocmInstallationDetector> RocmInstallation;
private:
void AddDeploymentTarget(llvm::opt::DerivedArgList &Args) const;
@@ -323,7 +350,7 @@ public:
bool isKernelStatic() const override {
return (!(isTargetIPhoneOS() && !isIPhoneOSVersionLT(6, 0)) &&
- !isTargetWatchOS());
+ !isTargetWatchOS() && !isTargetDriverKit());
}
void addProfileRTLibs(const llvm::opt::ArgList &Args,
@@ -379,6 +406,16 @@ public:
return isTargetIPhoneOS() || isTargetIOSSimulator();
}
+ bool isTargetXROSDevice() const {
+ return TargetPlatform == XROS && TargetEnvironment == NativeEnvironment;
+ }
+
+ bool isTargetXROSSimulator() const {
+ return TargetPlatform == XROS && TargetEnvironment == Simulator;
+ }
+
+ bool isTargetXROS() const { return TargetPlatform == XROS; }
+
bool isTargetTvOS() const {
assert(TargetInitialized && "Target not initialized!");
return TargetPlatform == TvOS && TargetEnvironment == NativeEnvironment;
@@ -409,6 +446,11 @@ public:
return TargetPlatform == WatchOS;
}
+ bool isTargetDriverKit() const {
+ assert(TargetInitialized && "Target not initialized!");
+ return TargetPlatform == DriverKit;
+ }
+
bool isTargetMacCatalyst() const {
return TargetPlatform == IPhoneOS && TargetEnvironment == MacCatalyst;
}
@@ -473,6 +515,10 @@ protected:
llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadKind) const override;
+ void addClangCC1ASTargetOptions(
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CC1ASArgs) const override;
+
StringRef getPlatformFamily() const;
StringRef getOSLibraryNameSuffix(bool IgnoreSim = false) const override;
@@ -512,7 +558,8 @@ public:
GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
// Stack protectors default to on for user code on 10.5,
// and for everything in 10.6 and beyond
- if (isTargetIOSBased() || isTargetWatchOSBased())
+ if (isTargetIOSBased() || isTargetWatchOSBased() || isTargetDriverKit() ||
+ isTargetXROS())
return LangOptions::SSPOn;
else if (isTargetMacOSBased() && !isMacosxVersionLT(10, 6))
return LangOptions::SSPOn;
@@ -590,7 +637,8 @@ private:
llvm::StringRef ArchDir,
llvm::StringRef BitDir) const;
- llvm::StringRef GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const;
+ llvm::SmallString<128>
+ GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const;
};
} // end namespace toolchains
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/DragonFly.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/DragonFly.cpp
index 9568b47e89e6..9942fc632e0a 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/DragonFly.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/DragonFly.cpp
@@ -12,6 +12,7 @@
#include "clang/Driver/Driver.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Support/Path.h"
using namespace clang::driver;
using namespace clang::driver::tools;
@@ -19,21 +20,19 @@ using namespace clang::driver::toolchains;
using namespace clang;
using namespace llvm::opt;
-/// DragonFly Tools
-
-// For now, DragonFly Assemble does just about the same as for
-// FreeBSD, but this may change soon.
void dragonfly::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
- claimNoWarnArgs(Args);
+ const auto &ToolChain = static_cast<const DragonFly &>(getToolChain());
ArgStringList CmdArgs;
+ claimNoWarnArgs(Args);
+
// When building 32-bit code on DragonFly/pc64, we have to explicitly
// instruct as in the base system to assemble 32-bit code.
- if (getToolChain().getArch() == llvm::Triple::x86)
+ if (ToolChain.getArch() == llvm::Triple::x86)
CmdArgs.push_back("--32");
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
@@ -44,7 +43,7 @@ void dragonfly::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));
@@ -55,21 +54,27 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
- const Driver &D = getToolChain().getDriver();
+ const auto &ToolChain = static_cast<const DragonFly &>(getToolChain());
+ const Driver &D = ToolChain.getDriver();
+ const llvm::Triple::ArchType Arch = ToolChain.getArch();
+ const bool Static = Args.hasArg(options::OPT_static);
+ const bool Shared = Args.hasArg(options::OPT_shared);
+ const bool Profiling = Args.hasArg(options::OPT_pg);
+ const bool Pie = Args.hasArg(options::OPT_pie);
ArgStringList CmdArgs;
if (!D.SysRoot.empty())
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
CmdArgs.push_back("--eh-frame-hdr");
- if (Args.hasArg(options::OPT_static)) {
+ if (Static) {
CmdArgs.push_back("-Bstatic");
} else {
if (Args.hasArg(options::OPT_rdynamic))
CmdArgs.push_back("-export-dynamic");
- if (Args.hasArg(options::OPT_shared))
- CmdArgs.push_back("-Bshareable");
- else {
+ if (Shared)
+ CmdArgs.push_back("-shared");
+ else if (!Args.hasArg(options::OPT_r)) {
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back("/usr/libexec/ld-elf.so.2");
}
@@ -79,75 +84,92 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// When building 32-bit code on DragonFly/pc64, we have to explicitly
// instruct ld in the base system to link 32-bit code.
- if (getToolChain().getArch() == llvm::Triple::x86) {
+ if (Arch == llvm::Triple::x86) {
CmdArgs.push_back("-m");
CmdArgs.push_back("elf_i386");
}
+ assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- } else {
- assert(Output.isNothing() && "Invalid output.");
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
- if (!Args.hasArg(options::OPT_shared)) {
- if (Args.hasArg(options::OPT_pg))
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("gcrt1.o")));
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
+ const char *crt1 = nullptr;
+ const char *crtbegin = nullptr;
+ if (!Shared) {
+ if (Profiling)
+ crt1 = "gcrt1.o";
else {
- if (Args.hasArg(options::OPT_pie))
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("Scrt1.o")));
+ if (Pie)
+ crt1 = "Scrt1.o";
else
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
+ crt1 = "crt1.o";
}
}
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
- if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtbeginS.o")));
+
+ if (Shared || Pie)
+ crtbegin = "crtbeginS.o";
else
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
- }
+ crtbegin = "crtbegin.o";
- Args.AddAllArgs(CmdArgs,
- {options::OPT_L, options::OPT_T_Group, options::OPT_e});
+ if (crt1)
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
+ }
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
+ Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
+ options::OPT_s, options::OPT_t, options::OPT_r});
+ ToolChain.AddFilePathLibArgs(Args, CmdArgs);
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
- CmdArgs.push_back("-L/usr/lib/gcc80");
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
- if (!Args.hasArg(options::OPT_static)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
+ options::OPT_r)) {
+ if (!Static) {
CmdArgs.push_back("-rpath");
CmdArgs.push_back("/usr/lib/gcc80");
}
+ // Use the static OpenMP runtime with -static-openmp
+ bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Static;
+ addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP);
+
if (D.CCCIsCXX()) {
- if (getToolChain().ShouldLinkCXXStdlib(Args))
- getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (ToolChain.ShouldLinkCXXStdlib(Args))
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ CmdArgs.push_back("-lm");
+ }
+
+ // Silence warnings when linking C code with a C++ '-stdlib' argument.
+ Args.ClaimAllArgs(options::OPT_stdlib_EQ);
+
+ // Additional linker set-up and flags for Fortran. This is required in order
+ // to generate executables. As Fortran runtime depends on the C runtime,
+ // these dependencies need to be listed before the C runtime below (i.e.
+ // AddRunTimeLibs).
+ if (D.IsFlangMode()) {
+ addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
+ addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
CmdArgs.push_back("-lm");
}
if (Args.hasArg(options::OPT_pthread))
CmdArgs.push_back("-lpthread");
- if (!Args.hasArg(options::OPT_nolibc)) {
+ if (!Args.hasArg(options::OPT_nolibc))
CmdArgs.push_back("-lc");
- }
- if (Args.hasArg(options::OPT_static) ||
- Args.hasArg(options::OPT_static_libgcc)) {
+ if (Static || Args.hasArg(options::OPT_static_libgcc)) {
CmdArgs.push_back("-lgcc");
CmdArgs.push_back("-lgcc_eh");
} else {
if (Args.hasArg(options::OPT_shared_libgcc)) {
CmdArgs.push_back("-lgcc_pic");
- if (!Args.hasArg(options::OPT_shared))
+ if (!Shared)
CmdArgs.push_back("-lgcc");
} else {
CmdArgs.push_back("-lgcc");
@@ -158,19 +180,21 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
- if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtendS.o")));
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
+ const char *crtend = nullptr;
+ if (Shared || Pie)
+ crtend ="crtendS.o";
else
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
+ crtend = "crtend.o";
+
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
}
- getToolChain().addProfileRTLibs(Args, CmdArgs);
+ ToolChain.addProfileRTLibs(Args, CmdArgs);
- const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
+ const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
C.addCommand(std::make_unique<Command>(JA, *this,
ResponseFileSupport::AtFileCurCP(),
Exec, CmdArgs, Inputs, Output));
@@ -188,8 +212,35 @@ DragonFly::DragonFly(const Driver &D, const llvm::Triple &Triple,
getProgramPaths().push_back(getDriver().Dir);
getFilePaths().push_back(getDriver().Dir + "/../lib");
- getFilePaths().push_back("/usr/lib");
- getFilePaths().push_back("/usr/lib/gcc80");
+ getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib"));
+ getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib/gcc80"));
+}
+
+void DragonFly::AddClangSystemIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ const Driver &D = getDriver();
+
+ if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
+ return;
+
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+ SmallString<128> Dir(D.ResourceDir);
+ llvm::sys::path::append(Dir, "include");
+ addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ }
+
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+
+ addExternCSystemInclude(DriverArgs, CC1Args,
+ concat(D.SysRoot, "/usr/include"));
+}
+
+void DragonFly::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ addLibStdCXXIncludePaths(concat(getDriver().SysRoot, "/usr/include/c++/8.0"), "", "",
+ DriverArgs, CC1Args);
}
Tool *DragonFly::buildAssembler() const {
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/DragonFly.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/DragonFly.h
index 3ed5acefaefb..715f6b45519b 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/DragonFly.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/DragonFly.h
@@ -16,9 +16,10 @@
namespace clang {
namespace driver {
namespace tools {
-/// dragonfly -- Directly call GNU Binutils assembler and linker
+
+/// Directly call GNU Binutils assembler and linker
namespace dragonfly {
-class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
+class LLVM_LIBRARY_VISIBILITY Assembler final : public Tool {
public:
Assembler(const ToolChain &TC)
: Tool("dragonfly::Assembler", "assembler", TC) {}
@@ -31,7 +32,7 @@ public:
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
public:
Linker(const ToolChain &TC) : Tool("dragonfly::Linker", "linker", TC) {}
@@ -55,6 +56,13 @@ public:
bool IsMathErrnoDefault() const override { return false; }
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void addLibStdCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Flang.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Flang.cpp
index 1bfad6115d51..03d68c3df7fb 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Flang.cpp
@@ -6,11 +6,17 @@
//
//===----------------------------------------------------------------------===//
-
#include "Flang.h"
+#include "Arch/RISCV.h"
#include "CommonArgs.h"
+#include "clang/Basic/CodeGenOptions.h"
#include "clang/Driver/Options.h"
+#include "llvm/Frontend/Debug/Options.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/RISCVISAInfo.h"
+#include "llvm/TargetParser/RISCVTargetParser.h"
#include <cassert>
@@ -19,54 +25,653 @@ using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;
-void Flang::AddFortranDialectOptions(const ArgList &Args,
+/// Add -x lang to \p CmdArgs for \p Input.
+static void addDashXForInput(const ArgList &Args, const InputInfo &Input,
+ ArgStringList &CmdArgs) {
+ CmdArgs.push_back("-x");
+ // Map the driver type to the frontend type.
+ CmdArgs.push_back(types::getTypeName(Input.getType()));
+}
+
+void Flang::addFortranDialectOptions(const ArgList &Args,
ArgStringList &CmdArgs) const {
- Args.AddAllArgs(
- CmdArgs, {options::OPT_ffixed_form, options::OPT_ffree_form,
- options::OPT_ffixed_line_length_EQ, options::OPT_fopenmp,
- options::OPT_fopenacc, options::OPT_finput_charset_EQ,
- options::OPT_fimplicit_none, options::OPT_fno_implicit_none,
- options::OPT_fbackslash, options::OPT_fno_backslash,
- options::OPT_flogical_abbreviations,
- options::OPT_fno_logical_abbreviations,
- options::OPT_fxor_operator, options::OPT_fno_xor_operator,
- options::OPT_falternative_parameter_statement,
- options::OPT_fdefault_real_8, options::OPT_fdefault_integer_8,
- options::OPT_fdefault_double_8, options::OPT_flarge_sizes});
-}
-
-void Flang::AddPreprocessingOptions(const ArgList &Args,
+ Args.addAllArgs(CmdArgs, {options::OPT_ffixed_form,
+ options::OPT_ffree_form,
+ options::OPT_ffixed_line_length_EQ,
+ options::OPT_fopenmp,
+ options::OPT_fopenmp_version_EQ,
+ options::OPT_fopenacc,
+ options::OPT_finput_charset_EQ,
+ options::OPT_fimplicit_none,
+ options::OPT_fno_implicit_none,
+ options::OPT_fbackslash,
+ options::OPT_fno_backslash,
+ options::OPT_flogical_abbreviations,
+ options::OPT_fno_logical_abbreviations,
+ options::OPT_fxor_operator,
+ options::OPT_fno_xor_operator,
+ options::OPT_falternative_parameter_statement,
+ options::OPT_fdefault_real_8,
+ options::OPT_fdefault_integer_8,
+ options::OPT_fdefault_double_8,
+ options::OPT_flarge_sizes,
+ options::OPT_fno_automatic});
+}
+
+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});
+}
+
+/// @C shouldLoopVersion
+///
+/// Check if Loop Versioning should be enabled.
+/// We look for the last of one of the following:
+/// -Ofast, -O4, -O<number> and -f[no-]version-loops-for-stride.
+/// Loop versioning is disabled if the last option is
+/// -fno-version-loops-for-stride.
+/// Loop versioning is enabled if the last option is one of:
+/// -floop-versioning
+/// -Ofast
+/// -O4
+/// -O3
+/// For all other cases, loop versioning is is disabled.
+///
+/// The gfortran compiler automatically enables the option for -O3 or -Ofast.
+///
+/// @return true if loop-versioning should be enabled, otherwise false.
+static bool shouldLoopVersion(const ArgList &Args) {
+ const Arg *LoopVersioningArg = Args.getLastArg(
+ options::OPT_Ofast, options::OPT_O, options::OPT_O4,
+ options::OPT_floop_versioning, options::OPT_fno_loop_versioning);
+ if (!LoopVersioningArg)
+ return false;
+
+ if (LoopVersioningArg->getOption().matches(options::OPT_fno_loop_versioning))
+ return false;
+
+ if (LoopVersioningArg->getOption().matches(options::OPT_floop_versioning))
+ return true;
+
+ if (LoopVersioningArg->getOption().matches(options::OPT_Ofast) ||
+ LoopVersioningArg->getOption().matches(options::OPT_O4))
+ return true;
+
+ if (LoopVersioningArg->getOption().matches(options::OPT_O)) {
+ StringRef S(LoopVersioningArg->getValue());
+ unsigned OptLevel = 0;
+ // Note -Os or Oz woould "fail" here, so return false. Which is the
+ // desiered behavior.
+ if (S.getAsInteger(10, OptLevel))
+ return false;
+
+ return OptLevel > 2;
+ }
+
+ llvm_unreachable("We should not end up here");
+ return false;
}
-void Flang::AddOtherOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
- Args.AddAllArgs(CmdArgs,
+void Flang::addOtherOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
+ Args.addAllArgs(CmdArgs,
{options::OPT_module_dir, options::OPT_fdebug_module_writer,
options::OPT_fintrinsic_modules_path, options::OPT_pedantic,
- options::OPT_std_EQ, options::OPT_W_Joined});
+ options::OPT_std_EQ, options::OPT_W_Joined,
+ options::OPT_fconvert_EQ, options::OPT_fpass_plugin_EQ,
+ options::OPT_funderscoring, options::OPT_fno_underscoring});
+
+ llvm::codegenoptions::DebugInfoKind DebugInfoKind;
+ if (Args.hasArg(options::OPT_gN_Group)) {
+ Arg *gNArg = Args.getLastArg(options::OPT_gN_Group);
+ DebugInfoKind = debugLevelToInfoKind(*gNArg);
+ } else if (Args.hasArg(options::OPT_g_Flag)) {
+ DebugInfoKind = llvm::codegenoptions::DebugLineTablesOnly;
+ } else {
+ DebugInfoKind = llvm::codegenoptions::NoDebugInfo;
+ }
+ addDebugInfoKind(CmdArgs, DebugInfoKind);
+}
+
+void Flang::addCodegenOptions(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ Arg *stackArrays =
+ Args.getLastArg(options::OPT_Ofast, options::OPT_fstack_arrays,
+ options::OPT_fno_stack_arrays);
+ if (stackArrays &&
+ !stackArrays->getOption().matches(options::OPT_fno_stack_arrays))
+ CmdArgs.push_back("-fstack-arrays");
+
+ if (shouldLoopVersion(Args))
+ CmdArgs.push_back("-fversion-loops-for-stride");
+
+ Args.addAllArgs(CmdArgs, {options::OPT_flang_experimental_hlfir,
+ options::OPT_flang_deprecated_no_hlfir,
+ options::OPT_flang_experimental_polymorphism,
+ options::OPT_fno_ppc_native_vec_elem_order,
+ options::OPT_fppc_native_vec_elem_order});
+}
+
+void Flang::addPicOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
+ // ParsePICArgs parses -fPIC/-fPIE and their variants and returns a tuple of
+ // (RelocationModel, PICLevel, IsPIE).
+ llvm::Reloc::Model RelocationModel;
+ unsigned PICLevel;
+ bool IsPIE;
+ std::tie(RelocationModel, PICLevel, IsPIE) =
+ ParsePICArgs(getToolChain(), Args);
+
+ if (auto *RMName = RelocationModelName(RelocationModel)) {
+ CmdArgs.push_back("-mrelocation-model");
+ CmdArgs.push_back(RMName);
+ }
+ if (PICLevel > 0) {
+ CmdArgs.push_back("-pic-level");
+ CmdArgs.push_back(PICLevel == 1 ? "1" : "2");
+ if (IsPIE)
+ CmdArgs.push_back("-pic-is-pie");
+ }
+}
+
+void Flang::AddAArch64TargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ // Handle -msve_vector_bits=<bits>
+ if (Arg *A = Args.getLastArg(options::OPT_msve_vector_bits_EQ)) {
+ 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("128+") ||
+ Val.equals("256+") || Val.equals("512+") || Val.equals("1024+") ||
+ Val.equals("2048+")) {
+ unsigned Bits = 0;
+ if (Val.ends_with("+"))
+ Val = Val.substr(0, Val.size() - 1);
+ else {
+ [[maybe_unused]] bool Invalid = Val.getAsInteger(10, Bits);
+ assert(!Invalid && "Failed to parse value");
+ CmdArgs.push_back(
+ Args.MakeArgString("-mvscale-max=" + llvm::Twine(Bits / 128)));
+ }
+
+ [[maybe_unused]] bool Invalid = Val.getAsInteger(10, Bits);
+ assert(!Invalid && "Failed to parse value");
+ CmdArgs.push_back(
+ 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"))
+ // Handle the unsupported values passed to msve-vector-bits.
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getSpelling() << Val;
+ }
+}
+
+void Flang::AddRISCVTargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ const llvm::Triple &Triple = getToolChain().getTriple();
+ // Handle -mrvv-vector-bits=<bits>
+ if (Arg *A = Args.getLastArg(options::OPT_mrvv_vector_bits_EQ)) {
+ StringRef Val = A->getValue();
+ const Driver &D = getToolChain().getDriver();
+
+ // Get minimum VLen from march.
+ unsigned MinVLen = 0;
+ StringRef Arch = riscv::getRISCVArch(Args, Triple);
+ auto ISAInfo = llvm::RISCVISAInfo::parseArchString(
+ Arch, /*EnableExperimentalExtensions*/ true);
+ // Ignore parsing error.
+ if (!errorToBool(ISAInfo.takeError()))
+ MinVLen = (*ISAInfo)->getMinVLen();
+
+ // If the value is "zvl", use MinVLen from march. Otherwise, try to parse
+ // as integer as long as we have a MinVLen.
+ unsigned Bits = 0;
+ if (Val.equals("zvl") && MinVLen >= llvm::RISCV::RVVBitsPerBlock) {
+ Bits = MinVLen;
+ } else if (!Val.getAsInteger(10, Bits)) {
+ // Only accept power of 2 values beteen RVVBitsPerBlock and 65536 that
+ // at least MinVLen.
+ if (Bits < MinVLen || Bits < llvm::RISCV::RVVBitsPerBlock ||
+ Bits > 65536 || !llvm::isPowerOf2_32(Bits))
+ Bits = 0;
+ }
+
+ // If we got a valid value try to use it.
+ if (Bits != 0) {
+ unsigned VScaleMin = Bits / llvm::RISCV::RVVBitsPerBlock;
+ CmdArgs.push_back(
+ Args.MakeArgString("-mvscale-max=" + llvm::Twine(VScaleMin)));
+ CmdArgs.push_back(
+ Args.MakeArgString("-mvscale-min=" + llvm::Twine(VScaleMin)));
+ } else if (!Val.equals("scalable")) {
+ // Handle the unsupported values passed to mrvv-vector-bits.
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getSpelling() << Val;
+ }
+ }
+}
+
+static void addVSDefines(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+
+ unsigned ver = 0;
+ const VersionTuple vt = TC.computeMSVCVersion(nullptr, Args);
+ ver = vt.getMajor() * 10000000 + vt.getMinor().value_or(0) * 100000 +
+ vt.getSubminor().value_or(0);
+ CmdArgs.push_back(Args.MakeArgString("-D_MSC_VER=" + Twine(ver / 100000)));
+ CmdArgs.push_back(Args.MakeArgString("-D_MSC_FULL_VER=" + Twine(ver)));
+ CmdArgs.push_back(Args.MakeArgString("-D_WIN32"));
+
+ llvm::Triple triple = TC.getTriple();
+ if (triple.isAArch64()) {
+ CmdArgs.push_back("-D_M_ARM64=1");
+ } else if (triple.isX86() && triple.isArch32Bit()) {
+ CmdArgs.push_back("-D_M_IX86=600");
+ } else if (triple.isX86() && triple.isArch64Bit()) {
+ CmdArgs.push_back("-D_M_X64=100");
+ } else {
+ llvm_unreachable(
+ "Flang on Windows only supports X86_32, X86_64 and AArch64");
+ }
+}
+
+static void processVSRuntimeLibrary(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ assert(TC.getTriple().isKnownWindowsMSVCEnvironment() &&
+ "can only add VS runtime library on Windows!");
+ // if -fno-fortran-main has been passed, skip linking Fortran_main.a
+ bool LinkFortranMain = !Args.hasArg(options::OPT_no_fortran_main);
+ if (TC.getTriple().isKnownWindowsMSVCEnvironment()) {
+ CmdArgs.push_back(Args.MakeArgString(
+ "--dependent-lib=" + TC.getCompilerRTBasename(Args, "builtins")));
+ }
+ unsigned RTOptionID = options::OPT__SLASH_MT;
+ if (auto *rtl = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
+ RTOptionID = llvm::StringSwitch<unsigned>(rtl->getValue())
+ .Case("static", options::OPT__SLASH_MT)
+ .Case("static_dbg", options::OPT__SLASH_MTd)
+ .Case("dll", options::OPT__SLASH_MD)
+ .Case("dll_dbg", options::OPT__SLASH_MDd)
+ .Default(options::OPT__SLASH_MT);
+ }
+ switch (RTOptionID) {
+ case options::OPT__SLASH_MT:
+ CmdArgs.push_back("-D_MT");
+ CmdArgs.push_back("--dependent-lib=libcmt");
+ if (LinkFortranMain)
+ CmdArgs.push_back("--dependent-lib=Fortran_main.static.lib");
+ CmdArgs.push_back("--dependent-lib=FortranRuntime.static.lib");
+ CmdArgs.push_back("--dependent-lib=FortranDecimal.static.lib");
+ break;
+ case options::OPT__SLASH_MTd:
+ CmdArgs.push_back("-D_MT");
+ CmdArgs.push_back("-D_DEBUG");
+ CmdArgs.push_back("--dependent-lib=libcmtd");
+ if (LinkFortranMain)
+ CmdArgs.push_back("--dependent-lib=Fortran_main.static_dbg.lib");
+ CmdArgs.push_back("--dependent-lib=FortranRuntime.static_dbg.lib");
+ CmdArgs.push_back("--dependent-lib=FortranDecimal.static_dbg.lib");
+ break;
+ case options::OPT__SLASH_MD:
+ CmdArgs.push_back("-D_MT");
+ CmdArgs.push_back("-D_DLL");
+ CmdArgs.push_back("--dependent-lib=msvcrt");
+ if (LinkFortranMain)
+ CmdArgs.push_back("--dependent-lib=Fortran_main.dynamic.lib");
+ CmdArgs.push_back("--dependent-lib=FortranRuntime.dynamic.lib");
+ CmdArgs.push_back("--dependent-lib=FortranDecimal.dynamic.lib");
+ break;
+ case options::OPT__SLASH_MDd:
+ CmdArgs.push_back("-D_MT");
+ CmdArgs.push_back("-D_DEBUG");
+ CmdArgs.push_back("-D_DLL");
+ CmdArgs.push_back("--dependent-lib=msvcrtd");
+ if (LinkFortranMain)
+ CmdArgs.push_back("--dependent-lib=Fortran_main.dynamic_dbg.lib");
+ CmdArgs.push_back("--dependent-lib=FortranRuntime.dynamic_dbg.lib");
+ CmdArgs.push_back("--dependent-lib=FortranDecimal.dynamic_dbg.lib");
+ break;
+ }
+}
+
+void Flang::AddAMDGPUTargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ if (Arg *A = Args.getLastArg(options::OPT_mcode_object_version_EQ)) {
+ StringRef Val = A->getValue();
+ CmdArgs.push_back(Args.MakeArgString("-mcode-object-version=" + Val));
+ }
+}
+
+void Flang::addTargetOptions(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ const ToolChain &TC = getToolChain();
+ const llvm::Triple &Triple = TC.getEffectiveTriple();
+ const Driver &D = TC.getDriver();
+
+ std::string CPU = getCPUName(D, Args, Triple);
+ if (!CPU.empty()) {
+ CmdArgs.push_back("-target-cpu");
+ CmdArgs.push_back(Args.MakeArgString(CPU));
+ }
+
+ // Add the target features.
+ switch (TC.getArch()) {
+ default:
+ break;
+ case llvm::Triple::aarch64:
+ getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);
+ AddAArch64TargetArgs(Args, CmdArgs);
+ break;
+
+ case llvm::Triple::r600:
+ case llvm::Triple::amdgcn:
+ getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);
+ AddAMDGPUTargetArgs(Args, CmdArgs);
+ break;
+ case llvm::Triple::riscv64:
+ getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);
+ AddRISCVTargetArgs(Args, CmdArgs);
+ break;
+ case llvm::Triple::x86_64:
+ getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);
+ break;
+ }
+
+ if (Arg *A = Args.getLastArg(options::OPT_fveclib)) {
+ StringRef Name = A->getValue();
+ if (Name == "SVML") {
+ if (Triple.getArch() != llvm::Triple::x86 &&
+ Triple.getArch() != llvm::Triple::x86_64)
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << Name << Triple.getArchName();
+ } else if (Name == "LIBMVEC-X86") {
+ if (Triple.getArch() != llvm::Triple::x86 &&
+ Triple.getArch() != llvm::Triple::x86_64)
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << Name << Triple.getArchName();
+ } else if (Name == "SLEEF" || Name == "ArmPL") {
+ if (Triple.getArch() != llvm::Triple::aarch64 &&
+ Triple.getArch() != llvm::Triple::aarch64_be)
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << Name << Triple.getArchName();
+ }
+
+ if (Triple.isOSDarwin()) {
+ // flang doesn't currently suport nostdlib, nodefaultlibs. Adding these
+ // here incase they are added someday
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ if (A->getValue() == StringRef{"Accelerate"}) {
+ CmdArgs.push_back("-framework");
+ CmdArgs.push_back("Accelerate");
+ }
+ }
+ }
+ A->render(Args, CmdArgs);
+ }
+
+ if (Triple.isKnownWindowsMSVCEnvironment()) {
+ processVSRuntimeLibrary(TC, Args, CmdArgs);
+ addVSDefines(TC, Args, CmdArgs);
+ }
+
+ // TODO: Add target specific flags, ABI, mtune option etc.
+}
+
+void Flang::addOffloadOptions(Compilation &C, const InputInfoList &Inputs,
+ const JobAction &JA, const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP);
+ bool IsHostOffloadingAction = JA.isHostOffloading(Action::OFK_OpenMP) ||
+ JA.isHostOffloading(C.getActiveOffloadKinds());
+
+ // Skips the primary input file, which is the input file that the compilation
+ // proccess will be executed upon (e.g. the host bitcode file) and
+ // adds other secondary input (e.g. device bitcode files for embedding to the
+ // -fembed-offload-object argument or the host IR file for proccessing
+ // during device compilation to the fopenmp-host-ir-file-path argument via
+ // OpenMPDeviceInput). This is condensed logic from the ConstructJob
+ // function inside of the Clang driver for pushing on further input arguments
+ // needed for offloading during various phases of compilation.
+ for (size_t i = 1; i < Inputs.size(); ++i) {
+ if (Inputs[i].getType() == types::TY_Nothing) {
+ // contains nothing, so it's skippable
+ } else if (IsHostOffloadingAction) {
+ CmdArgs.push_back(
+ Args.MakeArgString("-fembed-offload-object=" +
+ getToolChain().getInputFilename(Inputs[i])));
+ } else if (IsOpenMPDevice) {
+ if (Inputs[i].getFilename()) {
+ CmdArgs.push_back("-fopenmp-host-ir-file-path");
+ CmdArgs.push_back(Args.MakeArgString(Inputs[i].getFilename()));
+ } else {
+ llvm_unreachable("missing openmp host-ir file for device offloading");
+ }
+ } else {
+ llvm_unreachable(
+ "unexpectedly given multiple inputs or given unknown input");
+ }
+ }
+
+ if (IsOpenMPDevice) {
+ // -fopenmp-is-target-device is passed along to tell the frontend that it is
+ // generating code for a device, so that only the relevant code is emitted.
+ CmdArgs.push_back("-fopenmp-is-target-device");
+
+ // 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, 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");
+ if (Args.hasArg(options::OPT_fopenmp_assume_no_thread_state))
+ CmdArgs.push_back("-fopenmp-assume-no-thread-state");
+ if (Args.hasArg(options::OPT_fopenmp_assume_no_nested_parallelism))
+ CmdArgs.push_back("-fopenmp-assume-no-nested-parallelism");
+ if (Args.hasArg(options::OPT_nogpulib))
+ CmdArgs.push_back("-nogpulib");
+ }
+}
+
+static void addFloatingPointOptions(const Driver &D, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ StringRef FPContract;
+ bool HonorINFs = true;
+ bool HonorNaNs = true;
+ bool ApproxFunc = false;
+ bool SignedZeros = true;
+ bool AssociativeMath = false;
+ bool ReciprocalMath = false;
+
+ if (const Arg *A = Args.getLastArg(options::OPT_ffp_contract)) {
+ const StringRef Val = A->getValue();
+ if (Val == "fast" || Val == "off") {
+ FPContract = Val;
+ } else if (Val == "on") {
+ // Warn instead of error because users might have makefiles written for
+ // gfortran (which accepts -ffp-contract=on)
+ D.Diag(diag::warn_drv_unsupported_option_for_flang)
+ << Val << A->getOption().getName() << "off";
+ FPContract = "off";
+ } else
+ // Clang's "fast-honor-pragmas" option is not supported because it is
+ // non-standard
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getSpelling() << Val;
+ }
+
+ for (const Arg *A : Args) {
+ auto optId = A->getOption().getID();
+ switch (optId) {
+ // if this isn't an FP option, skip the claim below
+ default:
+ continue;
+
+ case options::OPT_fhonor_infinities:
+ HonorINFs = true;
+ break;
+ 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_fsigned_zeros:
+ SignedZeros = true;
+ break;
+ case options::OPT_fno_signed_zeros:
+ SignedZeros = false;
+ break;
+ case options::OPT_fassociative_math:
+ AssociativeMath = true;
+ break;
+ case options::OPT_fno_associative_math:
+ AssociativeMath = false;
+ break;
+ case options::OPT_freciprocal_math:
+ ReciprocalMath = true;
+ break;
+ case options::OPT_fno_reciprocal_math:
+ ReciprocalMath = false;
+ break;
+ case options::OPT_Ofast:
+ [[fallthrough]];
+ case options::OPT_ffast_math:
+ HonorINFs = false;
+ HonorNaNs = false;
+ AssociativeMath = true;
+ ReciprocalMath = true;
+ ApproxFunc = true;
+ SignedZeros = false;
+ FPContract = "fast";
+ break;
+ case options::OPT_fno_fast_math:
+ HonorINFs = true;
+ HonorNaNs = true;
+ AssociativeMath = false;
+ ReciprocalMath = false;
+ ApproxFunc = false;
+ SignedZeros = true;
+ // -fno-fast-math should undo -ffast-math so I return FPContract to the
+ // default. It is important to check it is "fast" (the default) so that
+ // --ffp-contract=off -fno-fast-math --> -ffp-contract=off
+ if (FPContract == "fast")
+ FPContract = "";
+ break;
+ }
+
+ // If we handled this option claim it
+ A->claim();
+ }
+
+ if (!HonorINFs && !HonorNaNs && AssociativeMath && ReciprocalMath &&
+ ApproxFunc && !SignedZeros &&
+ (FPContract == "fast" || FPContract == "")) {
+ CmdArgs.push_back("-ffast-math");
+ return;
+ }
+
+ if (!FPContract.empty())
+ CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + FPContract));
+
+ if (!HonorINFs)
+ CmdArgs.push_back("-menable-no-infs");
+
+ if (!HonorNaNs)
+ CmdArgs.push_back("-menable-no-nans");
+
+ if (ApproxFunc)
+ CmdArgs.push_back("-fapprox-func");
+
+ if (!SignedZeros)
+ CmdArgs.push_back("-fno-signed-zeros");
+
+ if (AssociativeMath && !SignedZeros)
+ CmdArgs.push_back("-mreassociate");
+
+ if (ReciprocalMath)
+ CmdArgs.push_back("-freciprocal-math");
+}
+
+static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs,
+ const InputInfo &Input) {
+ StringRef Format = "yaml";
+ if (const Arg *A = Args.getLastArg(options::OPT_fsave_optimization_record_EQ))
+ Format = A->getValue();
+
+ CmdArgs.push_back("-opt-record-file");
+
+ const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);
+ if (A) {
+ CmdArgs.push_back(A->getValue());
+ } else {
+ SmallString<128> F;
+
+ if (Args.hasArg(options::OPT_c) || Args.hasArg(options::OPT_S)) {
+ if (Arg *FinalOutput = Args.getLastArg(options::OPT_o))
+ F = FinalOutput->getValue();
+ }
+
+ if (F.empty()) {
+ // Use the input filename.
+ F = llvm::sys::path::stem(Input.getBaseInput());
+ }
+
+ SmallString<32> Extension;
+ Extension += "opt.";
+ Extension += Format;
+
+ llvm::sys::path::replace_extension(F, Extension);
+ CmdArgs.push_back(Args.MakeArgString(F));
+ }
+
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) {
+ CmdArgs.push_back("-opt-record-passes");
+ CmdArgs.push_back(A->getValue());
+ }
+
+ if (!Format.empty()) {
+ CmdArgs.push_back("-opt-record-format");
+ CmdArgs.push_back(Format.data());
+ }
}
void Flang::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const ArgList &Args, const char *LinkingOutput) const {
const auto &TC = getToolChain();
- // TODO: Once code-generation is available, this will need to be commented
- // out.
- // const llvm::Triple &Triple = TC.getEffectiveTriple();
- // const std::string &TripleStr = Triple.getTriple();
+ const llvm::Triple &Triple = TC.getEffectiveTriple();
+ const std::string &TripleStr = Triple.getTriple();
+ const Driver &D = TC.getDriver();
ArgStringList CmdArgs;
+ DiagnosticsEngine &Diags = D.getDiags();
// Invoke ourselves in -fc1 mode.
CmdArgs.push_back("-fc1");
- // TODO: Once code-generation is available, this will need to be commented
- // out.
// Add the "effective" target triple.
- // CmdArgs.push_back("-triple");
- // CmdArgs.push_back(Args.MakeArgString(TripleStr));
+ CmdArgs.push_back("-triple");
+ CmdArgs.push_back(Args.MakeArgString(TripleStr));
if (isa<PreprocessJobAction>(JA)) {
CmdArgs.push_back("-E");
@@ -98,27 +703,122 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
// Add preprocessing options like -I, -D, etc. if we are using the
// preprocessor (i.e. skip when dealing with e.g. binary files).
if (types::getPreprocessedType(InputType) != types::TY_INVALID)
- AddPreprocessingOptions(Args, CmdArgs);
+ addPreprocessingOptions(Args, CmdArgs);
- AddFortranDialectOptions(Args, CmdArgs);
+ addFortranDialectOptions(Args, CmdArgs);
+
+ // Color diagnostics are parsed by the driver directly from argv and later
+ // re-parsed to construct this job; claim any possible color diagnostic here
+ // to avoid warn_drv_unused_argument.
+ Args.getLastArg(options::OPT_fcolor_diagnostics,
+ options::OPT_fno_color_diagnostics);
+ if (Diags.getDiagnosticOptions().ShowColors)
+ CmdArgs.push_back("-fcolor-diagnostics");
+
+ // LTO mode is parsed by the Clang driver library.
+ LTOKind LTOMode = D.getLTOMode(/* IsOffload */ false);
+ assert(LTOMode != LTOK_Unknown && "Unknown LTO mode.");
+ if (LTOMode == LTOK_Full)
+ CmdArgs.push_back("-flto=full");
+ else if (LTOMode == LTOK_Thin) {
+ Diags.Report(
+ Diags.getCustomDiagID(DiagnosticsEngine::Warning,
+ "the option '-flto=thin' is a work in progress"));
+ CmdArgs.push_back("-flto=thin");
+ }
+
+ // -fPIC and related options.
+ addPicOptions(Args, CmdArgs);
+
+ // Floating point related options
+ addFloatingPointOptions(D, Args, CmdArgs);
+
+ // Add target args, features, etc.
+ addTargetOptions(Args, CmdArgs);
+
+ // Add Codegen options
+ addCodegenOptions(Args, CmdArgs);
+
+ // Add R Group options
+ Args.AddAllArgs(CmdArgs, options::OPT_R_Group);
+
+ // Remarks can be enabled with any of the `-f.*optimization-record.*` flags.
+ if (willEmitRemarks(Args))
+ renderRemarksOptions(Args, CmdArgs, Input);
// Add other compile options
- AddOtherOptions(Args, CmdArgs);
+ addOtherOptions(Args, CmdArgs);
+
+ // Offloading related options
+ addOffloadOptions(C, Inputs, JA, Args, CmdArgs);
// Forward -Xflang arguments to -fc1
Args.AddAllArgValues(CmdArgs, options::OPT_Xflang);
+ CodeGenOptions::FramePointerKind FPKeepKind =
+ getFramePointerKind(Args, Triple);
+
+ const char *FPKeepKindStr = nullptr;
+ switch (FPKeepKind) {
+ case CodeGenOptions::FramePointerKind::None:
+ FPKeepKindStr = "-mframe-pointer=none";
+ break;
+ case CodeGenOptions::FramePointerKind::NonLeaf:
+ FPKeepKindStr = "-mframe-pointer=non-leaf";
+ break;
+ case CodeGenOptions::FramePointerKind::All:
+ FPKeepKindStr = "-mframe-pointer=all";
+ break;
+ }
+ assert(FPKeepKindStr && "unknown FramePointerKind");
+ CmdArgs.push_back(FPKeepKindStr);
+
+ // Forward -mllvm options to the LLVM option parser. In practice, this means
+ // forwarding to `-fc1` as that's where the LLVM parser is run.
+ for (const Arg *A : Args.filtered(options::OPT_mllvm)) {
+ A->claim();
+ A->render(Args, CmdArgs);
+ }
+
+ for (const Arg *A : Args.filtered(options::OPT_mmlir)) {
+ A->claim();
+ A->render(Args, CmdArgs);
+ }
+
+ // Remove any unsupported gfortran diagnostic options
+ for (const Arg *A : Args.filtered(options::OPT_flang_ignored_w_Group)) {
+ A->claim();
+ D.Diag(diag::warn_drv_unsupported_diag_option_for_flang)
+ << A->getOption().getName();
+ }
+
+ // Optimization level for CodeGen.
+ if (const Arg *A = Args.getLastArg(options::OPT_O_Group)) {
+ if (A->getOption().matches(options::OPT_O4)) {
+ CmdArgs.push_back("-O3");
+ D.Diag(diag::warn_O4_is_O3);
+ } else if (A->getOption().matches(options::OPT_Ofast)) {
+ CmdArgs.push_back("-O3");
+ } else {
+ A->render(Args, CmdArgs);
+ }
+ }
+
+ assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- } else {
- assert(Output.isNothing() && "Invalid output.");
}
assert(Input.isFilename() && "Invalid input.");
+
+ if (Args.getLastArg(options::OPT_save_temps_EQ))
+ Args.AddLastArg(CmdArgs, options::OPT_save_temps_EQ);
+
+ addDashXForInput(Args, Input, CmdArgs);
+
CmdArgs.push_back(Input.getFilename());
- const auto& D = C.getDriver();
// TODO: Replace flang-new with flang once the new driver replaces the
// throwaway driver
const char *Exec = Args.MakeArgString(D.GetProgramPath("flang-new", TC));
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Flang.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Flang.h
index efbdbe854e24..ec2e545a1d0b 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Flang.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Flang.h
@@ -29,7 +29,7 @@ private:
///
/// \param [in] Args The list of input driver arguments
/// \param [out] CmdArgs The list of output command arguments
- void AddFortranDialectOptions(const llvm::opt::ArgList &Args,
+ void addFortranDialectOptions(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
/// Extract preprocessing options from the driver arguments and add them to
@@ -37,14 +37,71 @@ private:
///
/// \param [in] Args The list of input driver arguments
/// \param [out] CmdArgs The list of output command arguments
- void AddPreprocessingOptions(const llvm::opt::ArgList &Args,
+ void addPreprocessingOptions(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
+
+ /// Extract PIC options from the driver arguments and add them to
+ /// the command arguments.
+ ///
+ /// \param [in] Args The list of input driver arguments
+ /// \param [out] CmdArgs The list of output command arguments
+ void addPicOptions(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+
+ /// Extract target options from the driver arguments and add them to
+ /// the command arguments.
+ ///
+ /// \param [in] Args The list of input driver arguments
+ /// \param [out] CmdArgs The list of output command arguments
+ void addTargetOptions(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+
+ /// Add specific options for AArch64 target.
+ ///
+ /// \param [in] Args The list of input driver arguments
+ /// \param [out] CmdArgs The list of output command arguments
+ void AddAArch64TargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+
+ /// Add specific options for AMDGPU target.
+ ///
+ /// \param [in] Args The list of input driver arguments
+ /// \param [out] CmdArgs The list of output command arguments
+ void AddAMDGPUTargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+
+ /// Add specific options for RISC-V target.
+ ///
+ /// \param [in] Args The list of input driver arguments
+ /// \param [out] CmdArgs The list of output command arguments
+ void AddRISCVTargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+
+ /// Extract offload options from the driver arguments and add them to
+ /// the command arguments.
+ /// \param [in] C The current compilation for the driver invocation
+ /// \param [in] Inputs The input infomration on the current file inputs
+ /// \param [in] JA The job action
+ /// \param [in] Args The list of input driver arguments
+ /// \param [out] CmdArgs The list of output command arguments
+ void addOffloadOptions(Compilation &C, const InputInfoList &Inputs,
+ const JobAction &JA, const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+
+ /// Extract options for code generation from the driver arguments and add them
+ /// to the command arguments.
+ ///
+ /// \param [in] Args The list of input driver arguments
+ /// \param [out] CmdArgs The list of output command arguments
+ void addCodegenOptions(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
+
/// Extract other compilation options from the driver arguments and add them
/// to the command arguments.
///
/// \param [in] Args The list of input driver arguments
/// \param [out] CmdArgs The list of output command arguments
- void AddOtherOptions(const llvm::opt::ArgList &Args,
+ void addOtherOptions(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
public:
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp
index 5dcf74dabf4f..b7c9e0e51cdb 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp
@@ -11,6 +11,7 @@
#include "Arch/Mips.h"
#include "Arch/Sparc.h"
#include "CommonArgs.h"
+#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
@@ -29,13 +30,16 @@ void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
- claimNoWarnArgs(Args);
- ArgStringList CmdArgs;
+ const auto &ToolChain = static_cast<const FreeBSD &>(getToolChain());
const auto &D = getToolChain().getDriver();
+ const llvm::Triple &Triple = ToolChain.getTriple();
+ ArgStringList CmdArgs;
+
+ claimNoWarnArgs(Args);
// When building 32-bit code on FreeBSD/amd64, we have to explicitly
// instruct as in the base system to assemble 32-bit code.
- switch (getToolChain().getArch()) {
+ switch (ToolChain.getArch()) {
default:
break;
case llvm::Triple::x86:
@@ -51,7 +55,7 @@ void freebsd::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());
@@ -59,7 +63,7 @@ void freebsd::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");
@@ -70,39 +74,27 @@ void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
A->claim();
}
- AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
+ AddAssemblerKPIC(ToolChain, Args, CmdArgs);
break;
}
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb: {
- arm::FloatABI ABI = arm::getARMFloatABI(getToolChain(), Args);
+ arm::FloatABI ABI = arm::getARMFloatABI(ToolChain, Args);
if (ABI == arm::FloatABI::Hard)
CmdArgs.push_back("-mfpu=vfp");
else
CmdArgs.push_back("-mfpu=softvfp");
- switch (getToolChain().getTriple().getEnvironment()) {
- case llvm::Triple::GNUEABIHF:
- case llvm::Triple::GNUEABI:
- case llvm::Triple::EABI:
- CmdArgs.push_back("-meabi=5");
- break;
-
- default:
- CmdArgs.push_back("-matpcs");
- }
+ CmdArgs.push_back("-meabi=5");
break;
}
- case llvm::Triple::sparc:
- case llvm::Triple::sparcel:
case llvm::Triple::sparcv9: {
- 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;
}
}
@@ -110,7 +102,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 {
@@ -128,7 +120,7 @@ void freebsd::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));
@@ -139,13 +131,12 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
- const toolchains::FreeBSD &ToolChain =
- static_cast<const toolchains::FreeBSD &>(getToolChain());
+ const auto &ToolChain = static_cast<const FreeBSD &>(getToolChain());
const Driver &D = ToolChain.getDriver();
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"
@@ -169,16 +160,14 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_rdynamic))
CmdArgs.push_back("-export-dynamic");
if (Args.hasArg(options::OPT_shared)) {
- CmdArgs.push_back("-Bshareable");
- } else {
+ CmdArgs.push_back("-shared");
+ } else if (!Args.hasArg(options::OPT_r)) {
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back("/libexec/ld-elf.so.1");
}
const llvm::Triple &T = ToolChain.getTriple();
- if (T.getOSMajorVersion() >= 9) {
- if (Arch == llvm::Triple::arm || Arch == llvm::Triple::sparc || T.isX86())
- CmdArgs.push_back("--hash-style=both");
- }
+ if (Arch == llvm::Triple::arm || T.isX86())
+ CmdArgs.push_back("--hash-style=both");
CmdArgs.push_back("--enable-new-dtags");
}
@@ -220,13 +209,10 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
else
CmdArgs.push_back("elf64ltsmip_fbsd");
break;
- case llvm::Triple::riscv32:
- CmdArgs.push_back("-m");
- CmdArgs.push_back("elf32lriscv");
- break;
case llvm::Triple::riscv64:
CmdArgs.push_back("-m");
CmdArgs.push_back("elf64lriscv");
+ CmdArgs.push_back("-X");
break;
default:
break;
@@ -240,14 +226,14 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- } else {
- assert(Output.isNothing() && "Invalid output.");
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
const char *crt1 = nullptr;
if (!Args.hasArg(options::OPT_shared)) {
if (Args.hasArg(options::OPT_pg))
@@ -275,16 +261,20 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_L);
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
- Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
- Args.AddAllArgs(CmdArgs, options::OPT_e);
- Args.AddAllArgs(CmdArgs, options::OPT_s);
- Args.AddAllArgs(CmdArgs, options::OPT_t);
- Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
- Args.AddAllArgs(CmdArgs, options::OPT_r);
+ Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s,
+ options::OPT_t, options::OPT_r});
if (D.isUsingLTO()) {
assert(!Inputs.empty() && "Must have at least one input.");
- addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs[0],
+ // Find the first filename InputInfo object.
+ auto Input = llvm::find_if(
+ Inputs, [](const InputInfo &II) -> bool { return II.isFilename(); });
+ if (Input == Inputs.end())
+ // For a very rare case, all of the inputs to the linker are
+ // InputArg. If that happens, just use the first InputInfo.
+ Input = Inputs.begin();
+
+ addLTOOptions(ToolChain, Args, CmdArgs, Output, *Input,
D.getLTOMode() == LTOK_Thin);
}
@@ -293,9 +283,10 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
- bool Profiling = Args.hasArg(options::OPT_pg) &&
- ToolChain.getTriple().getOSMajorVersion() < 14;
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ unsigned Major = ToolChain.getTriple().getOSMajorVersion();
+ bool Profiling = Args.hasArg(options::OPT_pg) && Major != 0 && Major < 14;
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
+ options::OPT_r)) {
// Use the static OpenMP runtime with -static-openmp
bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) &&
!Args.hasArg(options::OPT_static);
@@ -309,10 +300,27 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
else
CmdArgs.push_back("-lm");
}
+
+ // Silence warnings when linking C code with a C++ '-stdlib' argument.
+ Args.ClaimAllArgs(options::OPT_stdlib_EQ);
+
+ // Additional linker set-up and flags for Fortran. This is required in order
+ // to generate executables. As Fortran runtime depends on the C runtime,
+ // these dependencies need to be listed before the C runtime below (i.e.
+ // AddRunTimeLibs).
+ if (D.IsFlangMode()) {
+ addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
+ addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
+ if (Profiling)
+ CmdArgs.push_back("-lm_p");
+ else
+ CmdArgs.push_back("-lm");
+ }
+
if (NeedsSanitizerDeps)
- linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
+ linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs);
if (NeedsXRayDeps)
- linkXRayRuntimeDeps(ToolChain, CmdArgs);
+ linkXRayRuntimeDeps(ToolChain, Args, CmdArgs);
// FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
// the default system libraries. Just mimic this for now.
if (Profiling)
@@ -358,11 +366,14 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
+ const char *crtend = nullptr;
if (Args.hasArg(options::OPT_shared) || IsPIE)
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
+ crtend = "crtendS.o";
else
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
+ crtend = "crtend.o";
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
}
@@ -382,64 +393,71 @@ FreeBSD::FreeBSD(const Driver &D, const llvm::Triple &Triple,
// When targeting 32-bit platforms, look for '/usr/lib32/crt1.o' and fall
// back to '/usr/lib' if it doesn't exist.
- if ((Triple.getArch() == llvm::Triple::x86 || Triple.isMIPS32() ||
- Triple.isPPC32()) &&
- D.getVFS().exists(getDriver().SysRoot + "/usr/lib32/crt1.o"))
- getFilePaths().push_back(getDriver().SysRoot + "/usr/lib32");
+ if (Triple.isArch32Bit() &&
+ D.getVFS().exists(concat(getDriver().SysRoot, "/usr/lib32/crt1.o")))
+ getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib32"));
else
- getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
+ getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib"));
}
-ToolChain::CXXStdlibType FreeBSD::GetDefaultCXXStdlibType() const {
- if (getTriple().getOSMajorVersion() >= 10)
- return ToolChain::CST_Libcxx;
- return ToolChain::CST_Libstdcxx;
-}
+void FreeBSD::AddClangSystemIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ const Driver &D = getDriver();
-unsigned FreeBSD::GetDefaultDwarfVersion() const {
- if (getTriple().getOSMajorVersion() < 12)
- return 2;
- return 4;
+ if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
+ return;
+
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+ SmallString<128> Dir(D.ResourceDir);
+ llvm::sys::path::append(Dir, "include");
+ addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ }
+
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+
+ // Check for configure-time C include directories.
+ StringRef CIncludeDirs(C_INCLUDE_DIRS);
+ if (CIncludeDirs != "") {
+ SmallVector<StringRef, 5> dirs;
+ CIncludeDirs.split(dirs, ":");
+ for (StringRef dir : dirs) {
+ StringRef Prefix =
+ llvm::sys::path::is_absolute(dir) ? StringRef(D.SysRoot) : "";
+ addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
+ }
+ return;
+ }
+
+ addExternCSystemInclude(DriverArgs, CC1Args,
+ concat(D.SysRoot, "/usr/include"));
}
void FreeBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/usr/include/c++/v1");
-}
-
-void FreeBSD::addLibStdCxxIncludePaths(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const {
- addLibStdCXXIncludePaths(getDriver().SysRoot + "/usr/include/c++/4.2", "", "",
- DriverArgs, CC1Args);
+ concat(getDriver().SysRoot, "/usr/include/c++/v1"));
}
void FreeBSD::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
- CXXStdlibType Type = GetCXXStdlibType(Args);
- bool Profiling =
- Args.hasArg(options::OPT_pg) && getTriple().getOSMajorVersion() < 14;
-
- switch (Type) {
- case ToolChain::CST_Libcxx:
- CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++");
- break;
+ unsigned Major = getTriple().getOSMajorVersion();
+ bool Profiling = Args.hasArg(options::OPT_pg) && Major != 0 && Major < 14;
- case ToolChain::CST_Libstdcxx:
- CmdArgs.push_back(Profiling ? "-lstdc++_p" : "-lstdc++");
- break;
- }
+ CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
}
void FreeBSD::AddCudaIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
- CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
+ CudaInstallation->AddCudaIncludeArgs(DriverArgs, CC1Args);
}
void FreeBSD::AddHIPIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
- RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
+ RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args);
}
Tool *FreeBSD::buildAssembler() const {
@@ -448,26 +466,16 @@ Tool *FreeBSD::buildAssembler() const {
Tool *FreeBSD::buildLinker() const { return new tools::freebsd::Linker(*this); }
-llvm::ExceptionHandling FreeBSD::GetExceptionModel(const ArgList &Args) const {
- // FreeBSD uses SjLj exceptions on ARM oabi.
- switch (getTriple().getEnvironment()) {
- case llvm::Triple::GNUEABIHF:
- case llvm::Triple::GNUEABI:
- case llvm::Triple::EABI:
- return llvm::ExceptionHandling::None;
- default:
- if (getTriple().getArch() == llvm::Triple::arm ||
- getTriple().getArch() == llvm::Triple::thumb)
- return llvm::ExceptionHandling::SjLj;
- return llvm::ExceptionHandling::None;
- }
-}
-
bool FreeBSD::HasNativeLLVMSupport() const { return true; }
-bool FreeBSD::IsUnwindTablesDefault(const ArgList &Args) const { return true; }
+ToolChain::UnwindTableLevel
+FreeBSD::getDefaultUnwindTableLevel(const ArgList &Args) const {
+ return UnwindTableLevel::Asynchronous;
+}
-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;
@@ -479,12 +487,11 @@ SanitizerMask FreeBSD::getSupportedSanitizers() const {
Res |= SanitizerKind::PointerCompare;
Res |= SanitizerKind::PointerSubtract;
Res |= SanitizerKind::Vptr;
- if (IsX86_64 || IsMIPS64) {
+ if (IsAArch64 || IsX86_64 || IsMIPS64) {
Res |= SanitizerKind::Leak;
Res |= SanitizerKind::Thread;
}
- if (IsX86 || IsX86_64) {
- Res |= SanitizerKind::Function;
+ if (IsAArch64 || IsX86 || IsX86_64) {
Res |= SanitizerKind::SafeStack;
Res |= SanitizerKind::Fuzzer;
Res |= SanitizerKind::FuzzerNoLink;
@@ -492,18 +499,7 @@ SanitizerMask FreeBSD::getSupportedSanitizers() const {
if (IsAArch64 || IsX86_64) {
Res |= SanitizerKind::KernelAddress;
Res |= SanitizerKind::KernelMemory;
- }
- if (IsX86_64) {
Res |= SanitizerKind::Memory;
}
return Res;
}
-
-void FreeBSD::addClangTargetOptions(const ArgList &DriverArgs,
- ArgStringList &CC1Args,
- Action::OffloadKind) const {
- if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
- options::OPT_fno_use_init_array,
- getTriple().getOSMajorVersion() >= 12))
- CC1Args.push_back("-fno-use-init-array");
-}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.h
index abc0876cef26..7ab63905ed4f 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.h
@@ -17,9 +17,9 @@ namespace clang {
namespace driver {
namespace tools {
-/// freebsd -- Directly call GNU Binutils assembler and linker
+/// Directly call GNU Binutils assembler and linker
namespace freebsd {
-class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
+class LLVM_LIBRARY_VISIBILITY Assembler final : public Tool {
public:
Assembler(const ToolChain &TC)
: Tool("freebsd::Assembler", "assembler", TC) {}
@@ -32,7 +32,7 @@ public:
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
public:
Linker(const ToolChain &TC) : Tool("freebsd::Linker", "linker", TC) {}
@@ -58,12 +58,19 @@ public:
bool IsMathErrnoDefault() const override { return false; }
bool IsObjCNonFragileABIDefault() const override { return true; }
- CXXStdlibType GetDefaultCXXStdlibType() const override;
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
+ RuntimeLibType GetDefaultRuntimeLibType() const override {
+ return ToolChain::RLT_CompilerRT;
+ }
+ CXXStdlibType GetDefaultCXXStdlibType() const override {
+ return ToolChain::CST_Libcxx;
+ }
+
void addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- void
- addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
@@ -71,19 +78,14 @@ public:
void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- llvm::ExceptionHandling
- GetExceptionModel(const llvm::opt::ArgList &Args) const override;
- bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override;
- bool isPIEDefault() const override;
+ UnwindTableLevel
+ getDefaultUnwindTableLevel(const llvm::opt::ArgList &Args) const override;
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override;
SanitizerMask getSupportedSanitizers() const override;
- unsigned GetDefaultDwarfVersion() const override;
+ unsigned GetDefaultDwarfVersion() const override { return 4; }
// Until dtrace (via CTF) and LLDB can deal with distributed debug info,
// FreeBSD defaults to standalone/full debug info.
bool GetDefaultStandaloneDebug() const override { return true; }
- void
- addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args,
- Action::OffloadKind DeviceOffloadKind) const override;
protected:
Tool *buildAssembler() const override;
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Fuchsia.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Fuchsia.cpp
index fd9804a7f353..14b838500bec 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Fuchsia.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Fuchsia.cpp
@@ -12,6 +12,7 @@
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/MultilibBuilder.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "llvm/Option/ArgList.h"
@@ -33,10 +34,11 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
- const toolchains::Fuchsia &ToolChain =
- static_cast<const toolchains::Fuchsia &>(getToolChain());
+ const auto &ToolChain = static_cast<const Fuchsia &>(getToolChain());
const Driver &D = ToolChain.getDriver();
+ const llvm::Triple &Triple = ToolChain.getEffectiveTriple();
+
ArgStringList CmdArgs;
// Silence warning for "clang -g foo.o -o foo"
@@ -53,6 +55,9 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-z");
CmdArgs.push_back("now");
+ CmdArgs.push_back("-z");
+ CmdArgs.push_back("start-stop-visibility=hidden");
+
const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
if (llvm::sys::path::filename(Exec).equals_insensitive("ld.lld") ||
llvm::sys::path::stem(Exec).equals_insensitive("ld.lld")) {
@@ -60,6 +65,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");
}
@@ -82,6 +89,14 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("--hash-style=gnu");
}
+ if (ToolChain.getArch() == llvm::Triple::aarch64) {
+ CmdArgs.push_back("--execute-only");
+
+ std::string CPU = getCPUName(D, Args, Triple);
+ if (CPU.empty() || CPU == "generic" || CPU == "cortex-a53")
+ CmdArgs.push_back("--fix-cortex-a53-843419");
+ }
+
CmdArgs.push_back("--eh-frame-hdr");
if (Args.hasArg(options::OPT_static))
@@ -89,9 +104,9 @@ 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)) {
+ if (!Args.hasArg(options::OPT_shared) && !Args.hasArg(options::OPT_r)) {
std::string Dyld = D.DyldPrefix;
if (SanArgs.needsAsanRt() && SanArgs.needsSharedRt())
Dyld += "asan/";
@@ -104,32 +119,42 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(Dyld));
}
+ if (ToolChain.getArch() == llvm::Triple::riscv64)
+ CmdArgs.push_back("-X");
+
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
if (!Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("Scrt1.o")));
}
}
- Args.AddAllArgs(CmdArgs, options::OPT_L);
- Args.AddAllArgs(CmdArgs, options::OPT_u);
+ Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u});
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
if (D.isUsingLTO()) {
assert(!Inputs.empty() && "Must have at least one input.");
- addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs[0],
+ // Find the first filename InputInfo object.
+ auto Input = llvm::find_if(
+ Inputs, [](const InputInfo &II) -> bool { return II.isFilename(); });
+ if (Input == Inputs.end())
+ // For a very rare case, all of the inputs to the linker are
+ // InputArg. If that happens, just use the first InputInfo.
+ Input = Inputs.begin();
+
+ addLTOOptions(ToolChain, Args, CmdArgs, Output, *Input,
D.getLTOMode() == LTOK_Thin);
}
- bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
- bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
+ addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
- ToolChain.addProfileRTLibs(Args, CmdArgs);
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
+ options::OPT_r)) {
if (Args.hasArg(options::OPT_static))
CmdArgs.push_back("-Bdynamic");
@@ -149,11 +174,14 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- if (NeedsSanitizerDeps)
- linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
+ // Note that Fuchsia never needs to link in sanitizer runtime deps. Any
+ // sanitizer runtimes with system dependencies use the `.deplibs` feature
+ // instead.
+ addSanitizerRuntimes(ToolChain, Args, CmdArgs);
- if (NeedsXRayDeps)
- linkXRayRuntimeDeps(ToolChain, CmdArgs);
+ addXRayRuntime(ToolChain, Args, CmdArgs);
+
+ ToolChain.addProfileRTLibs(Args, CmdArgs);
AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
@@ -168,7 +196,53 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lc");
}
- C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ C.addCommand(std::make_unique<Command>(JA, *this,
+ ResponseFileSupport::AtFileCurCP(),
+ Exec, CmdArgs, Inputs, Output));
+}
+
+void fuchsia::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);
+
+ // ar tool command "llvm-ar <options> <output_file> <input_files>".
+ ArgStringList CmdArgs;
+ // Create and insert file members with a deterministic index.
+ CmdArgs.push_back("rcsD");
+ 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 char *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::AtFileCurCP(),
Exec, CmdArgs, Inputs, Output));
}
@@ -184,98 +258,82 @@ Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple,
if (!D.SysRoot.empty()) {
SmallString<128> P(D.SysRoot);
llvm::sys::path::append(P, "lib");
- getFilePaths().push_back(std::string(P.str()));
+ getFilePaths().push_back(std::string(P));
}
auto FilePaths = [&](const Multilib &M) -> std::vector<std::string> {
std::vector<std::string> FP;
- SmallString<128> P(getStdlibPath());
- llvm::sys::path::append(P, M.gccSuffix());
- FP.push_back(std::string(P.str()));
+ if (std::optional<std::string> Path = getStdlibPath()) {
+ SmallString<128> P(*Path);
+ llvm::sys::path::append(P, M.gccSuffix());
+ FP.push_back(std::string(P));
+ }
return FP;
};
Multilibs.push_back(Multilib());
// Use the noexcept variant with -fno-exceptions to avoid the extra overhead.
- Multilibs.push_back(Multilib("noexcept", {}, {}, 1)
- .flag("-fexceptions")
- .flag("+fno-exceptions"));
+ Multilibs.push_back(MultilibBuilder("noexcept", {}, {})
+ .flag("-fexceptions", /*Disallow=*/true)
+ .flag("-fno-exceptions")
+ .makeMultilib());
// ASan has higher priority because we always want the instrumentated version.
- Multilibs.push_back(Multilib("asan", {}, {}, 2)
- .flag("+fsanitize=address"));
+ Multilibs.push_back(MultilibBuilder("asan", {}, {})
+ .flag("-fsanitize=address")
+ .makeMultilib());
// Use the asan+noexcept variant with ASan and -fno-exceptions.
- Multilibs.push_back(Multilib("asan+noexcept", {}, {}, 3)
- .flag("+fsanitize=address")
- .flag("-fexceptions")
- .flag("+fno-exceptions"));
+ Multilibs.push_back(MultilibBuilder("asan+noexcept", {}, {})
+ .flag("-fsanitize=address")
+ .flag("-fexceptions", /*Disallow=*/true)
+ .flag("-fno-exceptions")
+ .makeMultilib());
// HWASan has higher priority because we always want the instrumentated
// version.
- Multilibs.push_back(
- Multilib("hwasan", {}, {}, 4).flag("+fsanitize=hwaddress"));
+ Multilibs.push_back(MultilibBuilder("hwasan", {}, {})
+ .flag("-fsanitize=hwaddress")
+ .makeMultilib());
// Use the hwasan+noexcept variant with HWASan and -fno-exceptions.
- Multilibs.push_back(Multilib("hwasan+noexcept", {}, {}, 5)
- .flag("+fsanitize=hwaddress")
- .flag("-fexceptions")
- .flag("+fno-exceptions"));
- // Use the relative vtables ABI.
- // TODO: Remove these multilibs once relative vtables are enabled by default
- // for Fuchsia.
- Multilibs.push_back(Multilib("relative-vtables", {}, {}, 6)
- .flag("+fexperimental-relative-c++-abi-vtables"));
- Multilibs.push_back(Multilib("relative-vtables+noexcept", {}, {}, 7)
- .flag("+fexperimental-relative-c++-abi-vtables")
- .flag("-fexceptions")
- .flag("+fno-exceptions"));
- Multilibs.push_back(Multilib("relative-vtables+asan", {}, {}, 8)
- .flag("+fexperimental-relative-c++-abi-vtables")
- .flag("+fsanitize=address"));
- Multilibs.push_back(Multilib("relative-vtables+asan+noexcept", {}, {}, 9)
- .flag("+fexperimental-relative-c++-abi-vtables")
- .flag("+fsanitize=address")
- .flag("-fexceptions")
- .flag("+fno-exceptions"));
- Multilibs.push_back(Multilib("relative-vtables+hwasan", {}, {}, 10)
- .flag("+fexperimental-relative-c++-abi-vtables")
- .flag("+fsanitize=hwaddress"));
- Multilibs.push_back(Multilib("relative-vtables+hwasan+noexcept", {}, {}, 11)
- .flag("+fexperimental-relative-c++-abi-vtables")
- .flag("+fsanitize=hwaddress")
- .flag("-fexceptions")
- .flag("+fno-exceptions"));
+ Multilibs.push_back(MultilibBuilder("hwasan+noexcept", {}, {})
+ .flag("-fsanitize=hwaddress")
+ .flag("-fexceptions", /*Disallow=*/true)
+ .flag("-fno-exceptions")
+ .makeMultilib());
// Use Itanium C++ ABI for the compat multilib.
- Multilibs.push_back(Multilib("compat", {}, {}, 12).flag("+fc++-abi=itanium"));
+ Multilibs.push_back(MultilibBuilder("compat", {}, {})
+ .flag("-fc++-abi=itanium")
+ .makeMultilib());
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",
+ bool Exceptions =
+ Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions, true);
+ addMultilibFlag(Exceptions, "-fexceptions", Flags);
+ addMultilibFlag(!Exceptions, "-fno-exceptions", Flags);
+ addMultilibFlag(getSanitizerArgs(Args).needsAsanRt(), "-fsanitize=address",
Flags);
+ addMultilibFlag(getSanitizerArgs(Args).needsHwasanRt(),
+ "-fsanitize=hwaddress", Flags);
- addMultilibFlag(
- Args.hasFlag(options::OPT_fexperimental_relative_cxx_abi_vtables,
- options::OPT_fno_experimental_relative_cxx_abi_vtables,
- /*default=*/false),
- "fexperimental-relative-c++-abi-vtables", Flags);
addMultilibFlag(Args.getLastArgValue(options::OPT_fcxx_abi_EQ) == "itanium",
- "fc++-abi=itanium", Flags);
+ "-fc++-abi=itanium", Flags);
Multilibs.setFilePathsCallback(FilePaths);
- if (Multilibs.select(Flags, SelectedMultilib))
- if (!SelectedMultilib.isDefault())
+ if (Multilibs.select(Flags, SelectedMultilibs)) {
+ // Ensure that -print-multi-directory only outputs one multilib directory.
+ Multilib LastSelected = SelectedMultilibs.back();
+ SelectedMultilibs = {LastSelected};
+
+ if (!SelectedMultilibs.back().isDefault())
if (const auto &PathsCallback = Multilibs.filePathsCallback())
- for (const auto &Path : PathsCallback(SelectedMultilib))
+ for (const auto &Path : PathsCallback(SelectedMultilibs.back()))
// Prepend the multilib path to ensure it takes the precedence.
getFilePaths().insert(getFilePaths().begin(), Path);
+ }
}
std::string Fuchsia::ComputeEffectiveClangTriple(const ArgList &Args,
@@ -288,6 +346,10 @@ Tool *Fuchsia::buildLinker() const {
return new tools::fuchsia::Linker(*this);
}
+Tool *Fuchsia::buildStaticLibTool() const {
+ return new tools::fuchsia::StaticLibTool(*this);
+}
+
ToolChain::RuntimeLibType Fuchsia::GetRuntimeLibType(
const ArgList &Args) const {
if (Arg *A = Args.getLastArg(clang::driver::options::OPT_rtlib_EQ)) {
@@ -358,8 +420,8 @@ void Fuchsia::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
void Fuchsia::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
- if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
- DriverArgs.hasArg(options::OPT_nostdincxx))
+ if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc,
+ options::OPT_nostdincxx))
return;
const Driver &D = getDriver();
@@ -400,6 +462,8 @@ void Fuchsia::AddCXXStdlibLibArgs(const ArgList &Args,
switch (GetCXXStdlibType(Args)) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
break;
case ToolChain::CST_Libstdcxx:
@@ -426,24 +490,14 @@ SanitizerMask Fuchsia::getDefaultSanitizers() const {
SanitizerMask Res;
switch (getTriple().getArch()) {
case llvm::Triple::aarch64:
+ case llvm::Triple::riscv64:
Res |= SanitizerKind::ShadowCallStack;
break;
case llvm::Triple::x86_64:
Res |= SanitizerKind::SafeStack;
break;
default:
- // TODO: Enable SafeStack on RISC-V once tested.
break;
}
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/contrib/llvm-project/clang/lib/Driver/ToolChains/Fuchsia.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Fuchsia.h
index 07adf9b7101d..619968f58502 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Fuchsia.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Fuchsia.h
@@ -18,7 +18,21 @@ namespace clang {
namespace driver {
namespace tools {
namespace fuchsia {
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+class LLVM_LIBRARY_VISIBILITY StaticLibTool : public Tool {
+public:
+ StaticLibTool(const ToolChain &TC)
+ : Tool("fuchsia::StaticLibTool", "llvm-ar", 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 Linker final : public Tool {
public:
Linker(const ToolChain &TC) : Tool("fuchsia::Linker", "ld.lld", TC) {}
@@ -41,20 +55,21 @@ public:
const llvm::opt::ArgList &Args);
bool HasNativeLLVMSupport() const override { return true; }
- bool IsIntegratedAssemblerDefault() const override { return true; }
bool IsMathErrnoDefault() const override { return false; }
- bool useRelaxRelocations() const override { return true; };
RuntimeLibType GetDefaultRuntimeLibType() const override {
return ToolChain::RLT_CompilerRT;
}
CXXStdlibType GetDefaultCXXStdlibType() const override {
return ToolChain::CST_Libcxx;
}
- bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override {
- return true;
+ UnwindTableLevel
+ getDefaultUnwindTableLevel(const llvm::opt::ArgList &Args) const override {
+ return UnwindTableLevel::Asynchronous;
}
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,32 +86,33 @@ 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
- GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
+ CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
+
+ bool IsAArch64OutlineAtomicsDefault(
+ const llvm::opt::ArgList &Args) const override {
+ return true;
+ }
- void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args,
- Action::OffloadKind DeviceOffloadKind) const override;
+ void
+ addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadKind) const override;
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- void
- AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
+ void AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
- const char *getDefaultLinker() const override {
- return "ld.lld";
- }
+ const char *getDefaultLinker() const override { return "ld.lld"; }
protected:
Tool *buildLinker() const override;
+ Tool *buildStaticLibTool() const override;
};
} // end namespace toolchains
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp
index da39f29e4619..e5e1b1d77269 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -8,6 +8,8 @@
#include "Gnu.h"
#include "Arch/ARM.h"
+#include "Arch/CSKY.h"
+#include "Arch/LoongArch.h"
#include "Arch/Mips.h"
#include "Arch/PPC.h"
#include "Arch/RISCV.h"
@@ -19,14 +21,18 @@
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/MultilibBuilder.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/TargetParser.h"
+#include "llvm/Support/RISCVISAInfo.h"
#include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/TargetParser/TargetParser.h"
#include <system_error>
using namespace clang::driver;
@@ -82,7 +88,7 @@ void tools::gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
RenderExtraToolArgs(JA, CmdArgs);
- // If using a driver driver, force the arch.
+ // If using a driver, force the arch.
if (getToolChain().getTriple().isOSDarwin()) {
CmdArgs.push_back("-arch");
CmdArgs.push_back(
@@ -112,11 +118,11 @@ void tools::gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
break;
}
+ assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
} else {
- assert(Output.isNothing() && "Unexpected output");
CmdArgs.push_back("-fsyntax-only");
}
@@ -215,30 +221,6 @@ void tools::gcc::Linker::RenderExtraToolArgs(const JobAction &JA,
// The types are (hopefully) good enough.
}
-// On Arm the endianness of the output file is determined by the target and
-// can be overridden by the pseudo-target flags '-mlittle-endian'/'-EL' and
-// '-mbig-endian'/'-EB'. Unlike other targets the flag does not result in a
-// normalized triple so we must handle the flag here.
-static bool isArmBigEndian(const llvm::Triple &Triple,
- const ArgList &Args) {
- bool IsBigEndian = false;
- switch (Triple.getArch()) {
- case llvm::Triple::armeb:
- case llvm::Triple::thumbeb:
- IsBigEndian = true;
- LLVM_FALLTHROUGH;
- case llvm::Triple::arm:
- case llvm::Triple::thumb:
- if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
- options::OPT_mbig_endian))
- IsBigEndian = !A->getOption().matches(options::OPT_mlittle_endian);
- break;
- default:
- break;
- }
- return IsBigEndian;
-}
-
static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
switch (T.getArch()) {
case llvm::Triple::x86:
@@ -253,7 +235,8 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
case llvm::Triple::thumb:
case llvm::Triple::armeb:
case llvm::Triple::thumbeb:
- return isArmBigEndian(T, Args) ? "armelfb_linux_eabi" : "armelf_linux_eabi";
+ return tools::arm::isARMBigEndian(T, Args) ? "armelfb_linux_eabi"
+ : "armelf_linux_eabi";
case llvm::Triple::m68k:
return "m68kelf";
case llvm::Triple::ppc:
@@ -277,6 +260,10 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
return "elf32_sparc";
case llvm::Triple::sparcv9:
return "elf64_sparc";
+ case llvm::Triple::loongarch32:
+ return "elf32loongarch";
+ case llvm::Triple::loongarch64:
+ return "elf64loongarch";
case llvm::Triple::mips:
return "elf32btsmip";
case llvm::Triple::mipsel:
@@ -299,32 +286,20 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
return "elf_x86_64";
case llvm::Triple::ve:
return "elf64ve";
+ case llvm::Triple::csky:
+ return "cskyelf_linux";
default:
return nullptr;
}
}
-static bool getPIE(const ArgList &Args, const ToolChain &TC) {
- if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_static) ||
- Args.hasArg(options::OPT_r) || Args.hasArg(options::OPT_static_pie))
- return false;
-
- Arg *A = Args.getLastArg(options::OPT_pie, options::OPT_no_pie,
- options::OPT_nopie);
- if (!A)
- return TC.isPIEDefault();
- return A->getOption().matches(options::OPT_pie);
-}
-
static bool getStaticPIE(const ArgList &Args, const ToolChain &TC) {
bool HasStaticPIE = Args.hasArg(options::OPT_static_pie);
- // -no-pie is an alias for -nopie. So, handling -nopie takes care of
- // -no-pie as well.
- if (HasStaticPIE && Args.hasArg(options::OPT_nopie)) {
+ if (HasStaticPIE && Args.hasArg(options::OPT_no_pie)) {
const Driver &D = TC.getDriver();
const llvm::opt::OptTable &Opts = D.getOpts();
- const char *StaticPIEName = Opts.getOptionName(options::OPT_static_pie);
- const char *NoPIEName = Opts.getOptionName(options::OPT_nopie);
+ StringRef StaticPIEName = Opts.getOptionName(options::OPT_static_pie);
+ StringRef NoPIEName = Opts.getOptionName(options::OPT_nopie);
D.Diag(diag::err_drv_cannot_mix_options) << StaticPIEName << NoPIEName;
}
return HasStaticPIE;
@@ -388,17 +363,16 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// Generic_ELF, so the static_cast might return a reference to a invalid
// instance (see PR45061). Ideally, the Linker constructor needs to take a
// Generic_ELF instead.
- const toolchains::Generic_ELF &ToolChain =
- static_cast<const toolchains::Generic_ELF &>(getToolChain());
+ const auto &ToolChain = static_cast<const Generic_ELF &>(getToolChain());
const Driver &D = ToolChain.getDriver();
const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
const llvm::Triple::ArchType Arch = ToolChain.getArch();
+ const bool isOHOSFamily = ToolChain.getTriple().isOHOSFamily();
const bool isAndroid = ToolChain.getTriple().isAndroid();
const bool IsIAMCU = ToolChain.getTriple().isOSIAMCU();
const bool IsVE = ToolChain.getTriple().isVE();
- const bool IsPIE = getPIE(Args, ToolChain);
const bool IsStaticPIE = getStaticPIE(Args, ToolChain);
const bool IsStatic = getStatic(Args);
const bool HasCRTBeginEndFiles =
@@ -418,49 +392,26 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (!D.SysRoot.empty())
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
- if (IsPIE)
- CmdArgs.push_back("-pie");
-
- if (IsStaticPIE) {
- CmdArgs.push_back("-static");
- CmdArgs.push_back("-pie");
- CmdArgs.push_back("--no-dynamic-linker");
- CmdArgs.push_back("-z");
- 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");
-
if (Args.hasArg(options::OPT_s))
CmdArgs.push_back("-s");
- if (Triple.isARM() || Triple.isThumb() || Triple.isAArch64()) {
- bool IsBigEndian = isArmBigEndian(Triple, Args);
+ if (Triple.isARM() || Triple.isThumb()) {
+ bool IsBigEndian = arm::isARMBigEndian(Triple, Args);
if (IsBigEndian)
arm::appendBE8LinkFlag(Args, CmdArgs, Triple);
- IsBigEndian = IsBigEndian || Arch == llvm::Triple::aarch64_be;
CmdArgs.push_back(IsBigEndian ? "-EB" : "-EL");
+ } else if (Triple.isAArch64()) {
+ CmdArgs.push_back(Arch == llvm::Triple::aarch64_be ? "-EB" : "-EL");
}
// 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);
+ if (Arch == llvm::Triple::aarch64 && (isAndroid || isOHOSFamily)) {
+ std::string CPU = getCPUName(D, Args, Triple);
if (CPU.empty() || CPU == "generic" || CPU == "cortex-a53")
CmdArgs.push_back("--fix-cortex-a53-843419");
}
- // Android does not allow shared text relocations. Emit a warning if the
- // user's code contains any.
- if (isAndroid)
- CmdArgs.push_back("--warn-shared-textrel");
-
ToolChain.addExtraOpts(CmdArgs);
CmdArgs.push_back("--eh-frame-hdr");
@@ -472,22 +423,29 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
D.Diag(diag::err_target_unknown_triple) << Triple.str();
return;
}
+ if (Triple.isRISCV())
+ CmdArgs.push_back("-X");
- if (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)) {
+ const bool IsShared = Args.hasArg(options::OPT_shared);
+ if (IsShared)
CmdArgs.push_back("-shared");
- }
-
- if (!IsStatic) {
+ bool IsPIE = false;
+ if (IsStaticPIE) {
+ CmdArgs.push_back("-static");
+ CmdArgs.push_back("-pie");
+ CmdArgs.push_back("--no-dynamic-linker");
+ CmdArgs.push_back("-z");
+ CmdArgs.push_back("text");
+ } else if (IsStatic) {
+ CmdArgs.push_back("-static");
+ } else if (!Args.hasArg(options::OPT_r)) {
if (Args.hasArg(options::OPT_rdynamic))
CmdArgs.push_back("-export-dynamic");
-
- if (!Args.hasArg(options::OPT_shared) && !IsStaticPIE) {
+ if (!IsShared) {
+ IsPIE = Args.hasFlag(options::OPT_pie, options::OPT_no_pie,
+ ToolChain.isPIEDefault(Args));
+ if (IsPIE)
+ CmdArgs.push_back("-pie");
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back(Args.MakeArgString(Twine(D.DyldPrefix) +
ToolChain.getDynamicLinker(Args)));
@@ -497,7 +455,8 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
if (!isAndroid && !IsIAMCU) {
const char *crt1 = nullptr;
if (!Args.hasArg(options::OPT_shared)) {
@@ -534,10 +493,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
@@ -549,16 +508,28 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// Add crtfastmath.o if available and fast math is enabled.
ToolChain.addFastMathRuntimeIfAvailable(Args, CmdArgs);
+
+ if (isAndroid && Args.hasFlag(options::OPT_fandroid_pad_segment,
+ options::OPT_fno_android_pad_segment, false))
+ CmdArgs.push_back(
+ Args.MakeArgString(ToolChain.GetFilePath("crt_pad_segment.o")));
}
- Args.AddAllArgs(CmdArgs, options::OPT_L);
- Args.AddAllArgs(CmdArgs, options::OPT_u);
+ Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u});
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
if (D.isUsingLTO()) {
assert(!Inputs.empty() && "Must have at least one input.");
- addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs[0],
+ // Find the first filename InputInfo object.
+ auto Input = llvm::find_if(
+ Inputs, [](const InputInfo &II) -> bool { return II.isFilename(); });
+ if (Input == Inputs.end())
+ // For a very rare case, all of the inputs to the linker are
+ // InputArg. If that happens, just use the first InputInfo.
+ Input = Inputs.begin();
+
+ addLTOOptions(ToolChain, Args, CmdArgs, Output, *Input,
D.getLTOMode() == LTOK_Thin);
}
@@ -569,11 +540,15 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
+
+ addHIPRuntimeLibArgs(ToolChain, C, Args, CmdArgs);
+
// The profile runtime also needs access to system libraries.
getToolChain().addProfileRTLibs(Args, CmdArgs);
if (D.CCCIsCXX() &&
- !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
+ options::OPT_r)) {
if (ToolChain.ShouldLinkCXXStdlib(Args)) {
bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
!Args.hasArg(options::OPT_static);
@@ -585,19 +560,30 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
CmdArgs.push_back("-lm");
}
+
// Silence warnings when linking C code with a C++ '-stdlib' argument.
Args.ClaimAllArgs(options::OPT_stdlib_EQ);
- if (!Args.hasArg(options::OPT_nostdlib)) {
+ // Additional linker set-up and flags for Fortran. This is required in order
+ // to generate executables. As Fortran runtime depends on the C runtime,
+ // these dependencies need to be listed before the C runtime below (i.e.
+ // AddRunTimeLibs).
+ if (D.IsFlangMode()) {
+ addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
+ addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
+ CmdArgs.push_back("-lm");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_r)) {
if (!Args.hasArg(options::OPT_nodefaultlibs)) {
if (IsStatic || IsStaticPIE)
CmdArgs.push_back("--start-group");
if (NeedsSanitizerDeps)
- linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
+ linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs);
if (NeedsXRayDeps)
- linkXRayRuntimeDeps(ToolChain, CmdArgs);
+ linkXRayRuntimeDeps(ToolChain, Args, CmdArgs);
bool WantPthread = Args.hasArg(options::OPT_pthread) ||
Args.hasArg(options::OPT_pthreads);
@@ -617,7 +603,19 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
- if (WantPthread && !isAndroid)
+ // LLVM support for atomics on 32-bit SPARC V8+ is incomplete, so
+ // forcibly link with libatomic as a workaround.
+ // TODO: Issue #41880 and D118021.
+ if (getToolChain().getTriple().getArch() == llvm::Triple::sparc) {
+ CmdArgs.push_back("--push-state");
+ CmdArgs.push_back("--as-needed");
+ CmdArgs.push_back("-latomic");
+ CmdArgs.push_back("--pop-state");
+ }
+
+ // We don't need libpthread neither for bionic (Android) nor for musl,
+ // (used by OHOS as runtime library).
+ if (WantPthread && !isAndroid && !isOHOSFamily)
CmdArgs.push_back("-lpthread");
if (Args.hasArg(options::OPT_fsplit_stack))
@@ -694,6 +692,10 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
unsigned PICLevel;
bool IsPIE;
const char *DefaultAssembler = "as";
+ // Enforce GNU as on Solaris; the native assembler's input syntax isn't fully
+ // compatible.
+ if (getToolChain().getTriple().isOSSolaris())
+ DefaultAssembler = "gas";
std::tie(RelocationModel, PICLevel, IsPIE) =
ParsePICArgs(getToolChain(), Args);
@@ -702,20 +704,16 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
CmdArgs.push_back("--compress-debug-sections");
} else {
StringRef Value = A->getValue();
- if (Value == "none" || Value == "zlib" || Value == "zlib-gnu") {
+ if (Value == "none" || Value == "zlib" || Value == "zstd") {
CmdArgs.push_back(
Args.MakeArgString("--compress-debug-sections=" + Twine(Value)));
} else {
D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << Value;
+ << A->getSpelling() << Value;
}
}
}
- if (getToolChain().isNoExecStackDefault()) {
- CmdArgs.push_back("--noexecstack");
- }
-
switch (getToolChain().getArch()) {
default:
break;
@@ -734,32 +732,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:
@@ -770,12 +768,14 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
StringRef MArchName = riscv::getRISCVArch(Args, getToolChain().getTriple());
CmdArgs.push_back("-march");
CmdArgs.push_back(MArchName.data());
+ if (!Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true))
+ Args.addOptOutFlag(CmdArgs, options::OPT_mrelax, options::OPT_mno_relax);
break;
}
case llvm::Triple::sparc:
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 +783,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);
@@ -794,7 +794,7 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
case llvm::Triple::thumb:
case llvm::Triple::thumbeb: {
const llvm::Triple &Triple2 = getToolChain().getTriple();
- CmdArgs.push_back(isArmBigEndian(Triple2, Args) ? "-EB" : "-EL");
+ CmdArgs.push_back(arm::isARMBigEndian(Triple2, Args) ? "-EB" : "-EL");
switch (Triple2.getSubArch()) {
case llvm::Triple::ARMSubArch_v7:
CmdArgs.push_back("-mfpu=neon");
@@ -823,6 +823,11 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
normalizeCPUNamesForAssembler(Args, CmdArgs);
Args.AddLastArg(CmdArgs, options::OPT_mfpu_EQ);
+ // The integrated assembler doesn't implement e_flags setting behavior for
+ // -meabi=gnu (gcc -mabi={apcs-gnu,atpcs} passes -meabi=gnu to gas). For
+ // compatibility we accept but warn.
+ if (Arg *A = Args.getLastArgNoClaim(options::OPT_mabi_EQ))
+ A->ignoreTargetSpecific();
break;
}
case llvm::Triple::aarch64:
@@ -834,6 +839,13 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
break;
}
+ // TODO: handle loongarch32.
+ case llvm::Triple::loongarch64: {
+ StringRef ABIName =
+ loongarch::getLoongArchABI(D, Args, getToolChain().getTriple());
+ CmdArgs.push_back(Args.MakeArgString("-mabi=" + ABIName));
+ break;
+ }
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
@@ -931,7 +943,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 {
@@ -950,6 +962,17 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
for (const auto &II : Inputs)
CmdArgs.push_back(II.getFilename());
+ if (Arg *A = Args.getLastArg(options::OPT_g_Flag, options::OPT_gN_Group,
+ options::OPT_gdwarf_2, options::OPT_gdwarf_3,
+ options::OPT_gdwarf_4, options::OPT_gdwarf_5,
+ options::OPT_gdwarf))
+ if (!A->getOption().matches(options::OPT_g0)) {
+ Args.AddLastArg(CmdArgs, options::OPT_g_Flag);
+
+ unsigned DwarfVersion = getDwarfVersion(getToolChain(), Args);
+ CmdArgs.push_back(Args.MakeArgString("-gdwarf-" + Twine(DwarfVersion)));
+ }
+
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath(DefaultAssembler));
C.addCommand(std::make_unique<Command>(JA, *this,
@@ -1013,46 +1036,47 @@ static bool isMSP430(llvm::Triple::ArchType Arch) {
return Arch == llvm::Triple::msp430;
}
-static Multilib makeMultilib(StringRef commonSuffix) {
- return Multilib(commonSuffix, commonSuffix, commonSuffix);
-}
-
static bool findMipsCsMultilibs(const Multilib::flags_list &Flags,
FilterNonExistent &NonExistent,
DetectedMultilibs &Result) {
// Check for Code Sourcery toolchain multilibs
MultilibSet CSMipsMultilibs;
{
- auto MArchMips16 = makeMultilib("/mips16").flag("+m32").flag("+mips16");
+ auto MArchMips16 = MultilibBuilder("/mips16").flag("-m32").flag("-mips16");
auto MArchMicroMips =
- makeMultilib("/micromips").flag("+m32").flag("+mmicromips");
+ MultilibBuilder("/micromips").flag("-m32").flag("-mmicromips");
- auto MArchDefault = makeMultilib("").flag("-mips16").flag("-mmicromips");
+ auto MArchDefault = MultilibBuilder("")
+ .flag("-mips16", /*Disallow=*/true)
+ .flag("-mmicromips", /*Disallow=*/true);
- auto UCLibc = makeMultilib("/uclibc").flag("+muclibc");
+ auto UCLibc = MultilibBuilder("/uclibc").flag("-muclibc");
- auto SoftFloat = makeMultilib("/soft-float").flag("+msoft-float");
+ auto SoftFloat = MultilibBuilder("/soft-float").flag("-msoft-float");
- auto Nan2008 = makeMultilib("/nan2008").flag("+mnan=2008");
+ auto Nan2008 = MultilibBuilder("/nan2008").flag("-mnan=2008");
- auto DefaultFloat =
- makeMultilib("").flag("-msoft-float").flag("-mnan=2008");
+ auto DefaultFloat = MultilibBuilder("")
+ .flag("-msoft-float", /*Disallow=*/true)
+ .flag("-mnan=2008", /*Disallow=*/true);
- auto BigEndian = makeMultilib("").flag("+EB").flag("-EL");
+ auto BigEndian =
+ MultilibBuilder("").flag("-EB").flag("-EL", /*Disallow=*/true);
- auto LittleEndian = makeMultilib("/el").flag("+EL").flag("-EB");
+ auto LittleEndian =
+ MultilibBuilder("/el").flag("-EL").flag("-EB", /*Disallow=*/true);
// Note that this one's osSuffix is ""
- auto MAbi64 = makeMultilib("")
+ auto MAbi64 = MultilibBuilder("")
.gccSuffix("/64")
.includeSuffix("/64")
- .flag("+mabi=n64")
- .flag("-mabi=n32")
- .flag("-m32");
+ .flag("-mabi=n64")
+ .flag("-mabi=n32", /*Disallow=*/true)
+ .flag("-m32", /*Disallow=*/true);
CSMipsMultilibs =
- MultilibSet()
+ MultilibSetBuilder()
.Either(MArchMips16, MArchMicroMips, MArchDefault)
.Maybe(UCLibc)
.Either(SoftFloat, Nan2008, DefaultFloat)
@@ -1062,10 +1086,11 @@ static bool findMipsCsMultilibs(const Multilib::flags_list &Flags,
.Maybe(MAbi64)
.FilterOut("/mips16.*/64")
.FilterOut("/micromips.*/64")
+ .makeMultilibSet()
.FilterOut(NonExistent)
.setIncludeDirsCallback([](const Multilib &M) {
std::vector<std::string> Dirs({"/include"});
- if (StringRef(M.includeSuffix()).startswith("/uclibc"))
+ if (StringRef(M.includeSuffix()).starts_with("/uclibc"))
Dirs.push_back(
"/../../../../mips-linux-gnu/libc/uclibc/usr/include");
else
@@ -1076,20 +1101,27 @@ static bool findMipsCsMultilibs(const Multilib::flags_list &Flags,
MultilibSet DebianMipsMultilibs;
{
- Multilib MAbiN32 =
- Multilib().gccSuffix("/n32").includeSuffix("/n32").flag("+mabi=n32");
+ MultilibBuilder MAbiN32 =
+ MultilibBuilder().gccSuffix("/n32").includeSuffix("/n32").flag(
+ "-mabi=n32");
- Multilib M64 = Multilib()
- .gccSuffix("/64")
- .includeSuffix("/64")
- .flag("+m64")
- .flag("-m32")
- .flag("-mabi=n32");
+ MultilibBuilder M64 = MultilibBuilder()
+ .gccSuffix("/64")
+ .includeSuffix("/64")
+ .flag("-m64")
+ .flag("-m32", /*Disallow=*/true)
+ .flag("-mabi=n32", /*Disallow=*/true);
- Multilib M32 = Multilib().flag("-m64").flag("+m32").flag("-mabi=n32");
+ MultilibBuilder M32 = MultilibBuilder()
+ .gccSuffix("/32")
+ .flag("-m64", /*Disallow=*/true)
+ .flag("-m32")
+ .flag("-mabi=n32", /*Disallow=*/true);
- DebianMipsMultilibs =
- MultilibSet().Either(M32, M64, MAbiN32).FilterOut(NonExistent);
+ DebianMipsMultilibs = MultilibSetBuilder()
+ .Either(M32, M64, MAbiN32)
+ .makeMultilibSet()
+ .FilterOut(NonExistent);
}
// Sort candidates. Toolchain that best meets the directories tree goes first.
@@ -1098,7 +1130,7 @@ static bool findMipsCsMultilibs(const Multilib::flags_list &Flags,
if (CSMipsMultilibs.size() < DebianMipsMultilibs.size())
std::iter_swap(Candidates, Candidates + 1);
for (const MultilibSet *Candidate : Candidates) {
- if (Candidate->select(Flags, Result.SelectedMultilib)) {
+ if (Candidate->select(Flags, Result.SelectedMultilibs)) {
if (Candidate == &DebianMipsMultilibs)
Result.BiarchSibling = Multilib();
Result.Multilibs = *Candidate;
@@ -1114,25 +1146,32 @@ static bool findMipsAndroidMultilibs(llvm::vfs::FileSystem &VFS, StringRef Path,
DetectedMultilibs &Result) {
MultilibSet AndroidMipsMultilibs =
- MultilibSet()
- .Maybe(Multilib("/mips-r2").flag("+march=mips32r2"))
- .Maybe(Multilib("/mips-r6").flag("+march=mips32r6"))
+ MultilibSetBuilder()
+ .Maybe(MultilibBuilder("/mips-r2", {}, {}).flag("-march=mips32r2"))
+ .Maybe(MultilibBuilder("/mips-r6", {}, {}).flag("-march=mips32r6"))
+ .makeMultilibSet()
.FilterOut(NonExistent);
MultilibSet AndroidMipselMultilibs =
- MultilibSet()
- .Either(Multilib().flag("+march=mips32"),
- Multilib("/mips-r2", "", "/mips-r2").flag("+march=mips32r2"),
- Multilib("/mips-r6", "", "/mips-r6").flag("+march=mips32r6"))
+ MultilibSetBuilder()
+ .Either(MultilibBuilder().flag("-march=mips32"),
+ MultilibBuilder("/mips-r2", "", "/mips-r2")
+ .flag("-march=mips32r2"),
+ MultilibBuilder("/mips-r6", "", "/mips-r6")
+ .flag("-march=mips32r6"))
+ .makeMultilibSet()
.FilterOut(NonExistent);
MultilibSet AndroidMips64elMultilibs =
- MultilibSet()
- .Either(
- Multilib().flag("+march=mips64r6"),
- Multilib("/32/mips-r1", "", "/mips-r1").flag("+march=mips32"),
- Multilib("/32/mips-r2", "", "/mips-r2").flag("+march=mips32r2"),
- Multilib("/32/mips-r6", "", "/mips-r6").flag("+march=mips32r6"))
+ MultilibSetBuilder()
+ .Either(MultilibBuilder().flag("-march=mips64r6"),
+ MultilibBuilder("/32/mips-r1", "", "/mips-r1")
+ .flag("-march=mips32"),
+ MultilibBuilder("/32/mips-r2", "", "/mips-r2")
+ .flag("-march=mips32r2"),
+ MultilibBuilder("/32/mips-r6", "", "/mips-r6")
+ .flag("-march=mips32r6"))
+ .makeMultilibSet()
.FilterOut(NonExistent);
MultilibSet *MS = &AndroidMipsMultilibs;
@@ -1140,7 +1179,7 @@ static bool findMipsAndroidMultilibs(llvm::vfs::FileSystem &VFS, StringRef Path,
MS = &AndroidMipselMultilibs;
else if (VFS.exists(Path + "/32"))
MS = &AndroidMips64elMultilibs;
- if (MS->select(Flags, Result.SelectedMultilib)) {
+ if (MS->select(Flags, Result.SelectedMultilibs)) {
Result.Multilibs = *MS;
return true;
}
@@ -1153,18 +1192,20 @@ static bool findMipsMuslMultilibs(const Multilib::flags_list &Flags,
// Musl toolchain multilibs
MultilibSet MuslMipsMultilibs;
{
- auto MArchMipsR2 = makeMultilib("")
+ auto MArchMipsR2 = MultilibBuilder("")
.osSuffix("/mips-r2-hard-musl")
- .flag("+EB")
- .flag("-EL")
- .flag("+march=mips32r2");
+ .flag("-EB")
+ .flag("-EL", /*Disallow=*/true)
+ .flag("-march=mips32r2");
- auto MArchMipselR2 = makeMultilib("/mipsel-r2-hard-musl")
- .flag("-EB")
- .flag("+EL")
- .flag("+march=mips32r2");
+ auto MArchMipselR2 = MultilibBuilder("/mipsel-r2-hard-musl")
+ .flag("-EB", /*Disallow=*/true)
+ .flag("-EL")
+ .flag("-march=mips32r2");
- MuslMipsMultilibs = MultilibSet().Either(MArchMipsR2, MArchMipselR2);
+ MuslMipsMultilibs = MultilibSetBuilder()
+ .Either(MArchMipsR2, MArchMipselR2)
+ .makeMultilibSet();
// Specify the callback that computes the include directories.
MuslMipsMultilibs.setIncludeDirsCallback([](const Multilib &M) {
@@ -1172,7 +1213,7 @@ static bool findMipsMuslMultilibs(const Multilib::flags_list &Flags,
{"/../sysroot" + M.osSuffix() + "/usr/include"});
});
}
- if (MuslMipsMultilibs.select(Flags, Result.SelectedMultilib)) {
+ if (MuslMipsMultilibs.select(Flags, Result.SelectedMultilibs)) {
Result.Multilibs = MuslMipsMultilibs;
return true;
}
@@ -1185,48 +1226,54 @@ static bool findMipsMtiMultilibs(const Multilib::flags_list &Flags,
// CodeScape MTI toolchain v1.2 and early.
MultilibSet MtiMipsMultilibsV1;
{
- auto MArchMips32 = makeMultilib("/mips32")
- .flag("+m32")
+ auto MArchMips32 = MultilibBuilder("/mips32")
+ .flag("-m32")
+ .flag("-m64", /*Disallow=*/true)
+ .flag("-mmicromips", /*Disallow=*/true)
+ .flag("-march=mips32");
+
+ auto MArchMicroMips = MultilibBuilder("/micromips")
+ .flag("-m32")
+ .flag("-m64", /*Disallow=*/true)
+ .flag("-mmicromips");
+
+ auto MArchMips64r2 = MultilibBuilder("/mips64r2")
+ .flag("-m32", /*Disallow=*/true)
+ .flag("-m64")
+ .flag("-march=mips64r2");
+
+ auto MArchMips64 = MultilibBuilder("/mips64")
+ .flag("-m32", /*Disallow=*/true)
.flag("-m64")
- .flag("-mmicromips")
- .flag("+march=mips32");
-
- auto MArchMicroMips = makeMultilib("/micromips")
- .flag("+m32")
- .flag("-m64")
- .flag("+mmicromips");
+ .flag("-march=mips64r2", /*Disallow=*/true);
- auto MArchMips64r2 = makeMultilib("/mips64r2")
- .flag("-m32")
- .flag("+m64")
- .flag("+march=mips64r2");
+ auto MArchDefault = MultilibBuilder("")
+ .flag("-m32")
+ .flag("-m64", /*Disallow=*/true)
+ .flag("-mmicromips", /*Disallow=*/true)
+ .flag("-march=mips32r2");
- auto MArchMips64 = makeMultilib("/mips64").flag("-m32").flag("+m64").flag(
- "-march=mips64r2");
+ auto Mips16 = MultilibBuilder("/mips16").flag("-mips16");
- auto MArchDefault = makeMultilib("")
- .flag("+m32")
- .flag("-m64")
- .flag("-mmicromips")
- .flag("+march=mips32r2");
+ auto UCLibc = MultilibBuilder("/uclibc").flag("-muclibc");
- auto Mips16 = makeMultilib("/mips16").flag("+mips16");
+ auto MAbi64 = MultilibBuilder("/64")
+ .flag("-mabi=n64")
+ .flag("-mabi=n32", /*Disallow=*/true)
+ .flag("-m32", /*Disallow=*/true);
- auto UCLibc = makeMultilib("/uclibc").flag("+muclibc");
+ auto BigEndian =
+ MultilibBuilder("").flag("-EB").flag("-EL", /*Disallow=*/true);
- auto MAbi64 =
- makeMultilib("/64").flag("+mabi=n64").flag("-mabi=n32").flag("-m32");
+ auto LittleEndian =
+ MultilibBuilder("/el").flag("-EL").flag("-EB", /*Disallow=*/true);
- auto BigEndian = makeMultilib("").flag("+EB").flag("-EL");
+ auto SoftFloat = MultilibBuilder("/sof").flag("-msoft-float");
- auto LittleEndian = makeMultilib("/el").flag("+EL").flag("-EB");
-
- auto SoftFloat = makeMultilib("/sof").flag("+msoft-float");
-
- auto Nan2008 = makeMultilib("/nan2008").flag("+mnan=2008");
+ auto Nan2008 = MultilibBuilder("/nan2008").flag("-mnan=2008");
MtiMipsMultilibsV1 =
- MultilibSet()
+ MultilibSetBuilder()
.Either(MArchMips32, MArchMicroMips, MArchMips64r2, MArchMips64,
MArchDefault)
.Maybe(UCLibc)
@@ -1243,10 +1290,11 @@ static bool findMipsMtiMultilibs(const Multilib::flags_list &Flags,
.Maybe(SoftFloat)
.Maybe(Nan2008)
.FilterOut(".*sof/nan2008")
+ .makeMultilibSet()
.FilterOut(NonExistent)
.setIncludeDirsCallback([](const Multilib &M) {
std::vector<std::string> Dirs({"/include"});
- if (StringRef(M.includeSuffix()).startswith("/uclibc"))
+ if (StringRef(M.includeSuffix()).starts_with("/uclibc"))
Dirs.push_back("/../../../../sysroot/uclibc/usr/include");
else
Dirs.push_back("/../../../../sysroot/usr/include");
@@ -1257,80 +1305,87 @@ static bool findMipsMtiMultilibs(const Multilib::flags_list &Flags,
// CodeScape IMG toolchain starting from v1.3.
MultilibSet MtiMipsMultilibsV2;
{
- auto BeHard = makeMultilib("/mips-r2-hard")
- .flag("+EB")
+ auto BeHard = MultilibBuilder("/mips-r2-hard")
+ .flag("-EB")
+ .flag("-msoft-float", /*Disallow=*/true)
+ .flag("-mnan=2008", /*Disallow=*/true)
+ .flag("-muclibc", /*Disallow=*/true);
+ auto BeSoft = MultilibBuilder("/mips-r2-soft")
+ .flag("-EB")
.flag("-msoft-float")
- .flag("-mnan=2008")
- .flag("-muclibc");
- auto BeSoft = makeMultilib("/mips-r2-soft")
- .flag("+EB")
- .flag("+msoft-float")
- .flag("-mnan=2008");
- auto ElHard = makeMultilib("/mipsel-r2-hard")
- .flag("+EL")
+ .flag("-mnan=2008", /*Disallow=*/true);
+ auto ElHard = MultilibBuilder("/mipsel-r2-hard")
+ .flag("-EL")
+ .flag("-msoft-float", /*Disallow=*/true)
+ .flag("-mnan=2008", /*Disallow=*/true)
+ .flag("-muclibc", /*Disallow=*/true);
+ auto ElSoft = MultilibBuilder("/mipsel-r2-soft")
+ .flag("-EL")
.flag("-msoft-float")
- .flag("-mnan=2008")
- .flag("-muclibc");
- auto ElSoft = makeMultilib("/mipsel-r2-soft")
- .flag("+EL")
- .flag("+msoft-float")
- .flag("-mnan=2008")
- .flag("-mmicromips");
- auto BeHardNan = makeMultilib("/mips-r2-hard-nan2008")
- .flag("+EB")
- .flag("-msoft-float")
- .flag("+mnan=2008")
- .flag("-muclibc");
- auto ElHardNan = makeMultilib("/mipsel-r2-hard-nan2008")
- .flag("+EL")
- .flag("-msoft-float")
- .flag("+mnan=2008")
- .flag("-muclibc")
- .flag("-mmicromips");
- auto BeHardNanUclibc = makeMultilib("/mips-r2-hard-nan2008-uclibc")
- .flag("+EB")
- .flag("-msoft-float")
- .flag("+mnan=2008")
- .flag("+muclibc");
- auto ElHardNanUclibc = makeMultilib("/mipsel-r2-hard-nan2008-uclibc")
- .flag("+EL")
- .flag("-msoft-float")
- .flag("+mnan=2008")
- .flag("+muclibc");
- auto BeHardUclibc = makeMultilib("/mips-r2-hard-uclibc")
- .flag("+EB")
- .flag("-msoft-float")
- .flag("-mnan=2008")
- .flag("+muclibc");
- auto ElHardUclibc = makeMultilib("/mipsel-r2-hard-uclibc")
- .flag("+EL")
- .flag("-msoft-float")
- .flag("-mnan=2008")
- .flag("+muclibc");
- auto ElMicroHardNan = makeMultilib("/micromipsel-r2-hard-nan2008")
- .flag("+EL")
- .flag("-msoft-float")
- .flag("+mnan=2008")
- .flag("+mmicromips");
- auto ElMicroSoft = makeMultilib("/micromipsel-r2-soft")
- .flag("+EL")
- .flag("+msoft-float")
- .flag("-mnan=2008")
- .flag("+mmicromips");
-
- auto O32 =
- makeMultilib("/lib").osSuffix("").flag("-mabi=n32").flag("-mabi=n64");
- auto N32 =
- makeMultilib("/lib32").osSuffix("").flag("+mabi=n32").flag("-mabi=n64");
- auto N64 =
- makeMultilib("/lib64").osSuffix("").flag("-mabi=n32").flag("+mabi=n64");
+ .flag("-mnan=2008", /*Disallow=*/true)
+ .flag("-mmicromips", /*Disallow=*/true);
+ auto BeHardNan = MultilibBuilder("/mips-r2-hard-nan2008")
+ .flag("-EB")
+ .flag("-msoft-float", /*Disallow=*/true)
+ .flag("-mnan=2008")
+ .flag("-muclibc", /*Disallow=*/true);
+ auto ElHardNan = MultilibBuilder("/mipsel-r2-hard-nan2008")
+ .flag("-EL")
+ .flag("-msoft-float", /*Disallow=*/true)
+ .flag("-mnan=2008")
+ .flag("-muclibc", /*Disallow=*/true)
+ .flag("-mmicromips", /*Disallow=*/true);
+ auto BeHardNanUclibc = MultilibBuilder("/mips-r2-hard-nan2008-uclibc")
+ .flag("-EB")
+ .flag("-msoft-float", /*Disallow=*/true)
+ .flag("-mnan=2008")
+ .flag("-muclibc");
+ auto ElHardNanUclibc = MultilibBuilder("/mipsel-r2-hard-nan2008-uclibc")
+ .flag("-EL")
+ .flag("-msoft-float", /*Disallow=*/true)
+ .flag("-mnan=2008")
+ .flag("-muclibc");
+ auto BeHardUclibc = MultilibBuilder("/mips-r2-hard-uclibc")
+ .flag("-EB")
+ .flag("-msoft-float", /*Disallow=*/true)
+ .flag("-mnan=2008", /*Disallow=*/true)
+ .flag("-muclibc");
+ auto ElHardUclibc = MultilibBuilder("/mipsel-r2-hard-uclibc")
+ .flag("-EL")
+ .flag("-msoft-float", /*Disallow=*/true)
+ .flag("-mnan=2008", /*Disallow=*/true)
+ .flag("-muclibc");
+ auto ElMicroHardNan = MultilibBuilder("/micromipsel-r2-hard-nan2008")
+ .flag("-EL")
+ .flag("-msoft-float", /*Disallow=*/true)
+ .flag("-mnan=2008")
+ .flag("-mmicromips");
+ auto ElMicroSoft = MultilibBuilder("/micromipsel-r2-soft")
+ .flag("-EL")
+ .flag("-msoft-float")
+ .flag("-mnan=2008", /*Disallow=*/true)
+ .flag("-mmicromips");
+
+ auto O32 = MultilibBuilder("/lib")
+ .osSuffix("")
+ .flag("-mabi=n32", /*Disallow=*/true)
+ .flag("-mabi=n64", /*Disallow=*/true);
+ auto N32 = MultilibBuilder("/lib32")
+ .osSuffix("")
+ .flag("-mabi=n32")
+ .flag("-mabi=n64", /*Disallow=*/true);
+ auto N64 = MultilibBuilder("/lib64")
+ .osSuffix("")
+ .flag("-mabi=n32", /*Disallow=*/true)
+ .flag("-mabi=n64");
MtiMipsMultilibsV2 =
- MultilibSet()
+ MultilibSetBuilder()
.Either({BeHard, BeSoft, ElHard, ElSoft, BeHardNan, ElHardNan,
BeHardNanUclibc, ElHardNanUclibc, BeHardUclibc,
ElHardUclibc, ElMicroHardNan, ElMicroSoft})
.Either(O32, N32, N64)
+ .makeMultilibSet()
.FilterOut(NonExistent)
.setIncludeDirsCallback([](const Multilib &M) {
return std::vector<std::string>({"/../../../../sysroot" +
@@ -1342,8 +1397,8 @@ static bool findMipsMtiMultilibs(const Multilib::flags_list &Flags,
{"/../../../../mips-mti-linux-gnu/lib" + M.gccSuffix()});
});
}
- for (auto Candidate : {&MtiMipsMultilibsV1, &MtiMipsMultilibsV2}) {
- if (Candidate->select(Flags, Result.SelectedMultilib)) {
+ for (auto *Candidate : {&MtiMipsMultilibsV1, &MtiMipsMultilibsV2}) {
+ if (Candidate->select(Flags, Result.SelectedMultilibs)) {
Result.Multilibs = *Candidate;
return true;
}
@@ -1357,18 +1412,24 @@ static bool findMipsImgMultilibs(const Multilib::flags_list &Flags,
// CodeScape IMG toolchain v1.2 and early.
MultilibSet ImgMultilibsV1;
{
- auto Mips64r6 = makeMultilib("/mips64r6").flag("+m64").flag("-m32");
+ auto Mips64r6 = MultilibBuilder("/mips64r6")
+ .flag("-m64")
+ .flag("-m32", /*Disallow=*/true);
- auto LittleEndian = makeMultilib("/el").flag("+EL").flag("-EB");
+ auto LittleEndian =
+ MultilibBuilder("/el").flag("-EL").flag("-EB", /*Disallow=*/true);
- auto MAbi64 =
- makeMultilib("/64").flag("+mabi=n64").flag("-mabi=n32").flag("-m32");
+ auto MAbi64 = MultilibBuilder("/64")
+ .flag("-mabi=n64")
+ .flag("-mabi=n32", /*Disallow=*/true)
+ .flag("-m32", /*Disallow=*/true);
ImgMultilibsV1 =
- MultilibSet()
+ MultilibSetBuilder()
.Maybe(Mips64r6)
.Maybe(MAbi64)
.Maybe(LittleEndian)
+ .makeMultilibSet()
.FilterOut(NonExistent)
.setIncludeDirsCallback([](const Multilib &M) {
return std::vector<std::string>(
@@ -1379,51 +1440,58 @@ static bool findMipsImgMultilibs(const Multilib::flags_list &Flags,
// CodeScape IMG toolchain starting from v1.3.
MultilibSet ImgMultilibsV2;
{
- auto BeHard = makeMultilib("/mips-r6-hard")
- .flag("+EB")
+ auto BeHard = MultilibBuilder("/mips-r6-hard")
+ .flag("-EB")
+ .flag("-msoft-float", /*Disallow=*/true)
+ .flag("-mmicromips", /*Disallow=*/true);
+ auto BeSoft = MultilibBuilder("/mips-r6-soft")
+ .flag("-EB")
.flag("-msoft-float")
- .flag("-mmicromips");
- auto BeSoft = makeMultilib("/mips-r6-soft")
- .flag("+EB")
- .flag("+msoft-float")
- .flag("-mmicromips");
- auto ElHard = makeMultilib("/mipsel-r6-hard")
- .flag("+EL")
+ .flag("-mmicromips", /*Disallow=*/true);
+ auto ElHard = MultilibBuilder("/mipsel-r6-hard")
+ .flag("-EL")
+ .flag("-msoft-float", /*Disallow=*/true)
+ .flag("-mmicromips", /*Disallow=*/true);
+ auto ElSoft = MultilibBuilder("/mipsel-r6-soft")
+ .flag("-EL")
.flag("-msoft-float")
- .flag("-mmicromips");
- auto ElSoft = makeMultilib("/mipsel-r6-soft")
- .flag("+EL")
- .flag("+msoft-float")
- .flag("-mmicromips");
- auto BeMicroHard = makeMultilib("/micromips-r6-hard")
- .flag("+EB")
+ .flag("-mmicromips", /*Disallow=*/true);
+ auto BeMicroHard = MultilibBuilder("/micromips-r6-hard")
+ .flag("-EB")
+ .flag("-msoft-float", /*Disallow=*/true)
+ .flag("-mmicromips");
+ auto BeMicroSoft = MultilibBuilder("/micromips-r6-soft")
+ .flag("-EB")
.flag("-msoft-float")
- .flag("+mmicromips");
- auto BeMicroSoft = makeMultilib("/micromips-r6-soft")
- .flag("+EB")
- .flag("+msoft-float")
- .flag("+mmicromips");
- auto ElMicroHard = makeMultilib("/micromipsel-r6-hard")
- .flag("+EL")
+ .flag("-mmicromips");
+ auto ElMicroHard = MultilibBuilder("/micromipsel-r6-hard")
+ .flag("-EL")
+ .flag("-msoft-float", /*Disallow=*/true)
+ .flag("-mmicromips");
+ auto ElMicroSoft = MultilibBuilder("/micromipsel-r6-soft")
+ .flag("-EL")
.flag("-msoft-float")
- .flag("+mmicromips");
- auto ElMicroSoft = makeMultilib("/micromipsel-r6-soft")
- .flag("+EL")
- .flag("+msoft-float")
- .flag("+mmicromips");
-
- auto O32 =
- makeMultilib("/lib").osSuffix("").flag("-mabi=n32").flag("-mabi=n64");
- auto N32 =
- makeMultilib("/lib32").osSuffix("").flag("+mabi=n32").flag("-mabi=n64");
- auto N64 =
- makeMultilib("/lib64").osSuffix("").flag("-mabi=n32").flag("+mabi=n64");
+ .flag("-mmicromips");
+
+ auto O32 = MultilibBuilder("/lib")
+ .osSuffix("")
+ .flag("-mabi=n32", /*Disallow=*/true)
+ .flag("-mabi=n64", /*Disallow=*/true);
+ auto N32 = MultilibBuilder("/lib32")
+ .osSuffix("")
+ .flag("-mabi=n32")
+ .flag("-mabi=n64", /*Disallow=*/true);
+ auto N64 = MultilibBuilder("/lib64")
+ .osSuffix("")
+ .flag("-mabi=n32", /*Disallow=*/true)
+ .flag("-mabi=n64");
ImgMultilibsV2 =
- MultilibSet()
+ MultilibSetBuilder()
.Either({BeHard, BeSoft, ElHard, ElSoft, BeMicroHard, BeMicroSoft,
ElMicroHard, ElMicroSoft})
.Either(O32, N32, N64)
+ .makeMultilibSet()
.FilterOut(NonExistent)
.setIncludeDirsCallback([](const Multilib &M) {
return std::vector<std::string>({"/../../../../sysroot" +
@@ -1435,8 +1503,8 @@ static bool findMipsImgMultilibs(const Multilib::flags_list &Flags,
{"/../../../../mips-img-linux-gnu/lib" + M.gccSuffix()});
});
}
- for (auto Candidate : {&ImgMultilibsV1, &ImgMultilibsV2}) {
- if (Candidate->select(Flags, Result.SelectedMultilib)) {
+ for (auto *Candidate : {&ImgMultilibsV1, &ImgMultilibsV2}) {
+ if (Candidate->select(Flags, Result.SelectedMultilibs)) {
Result.Multilibs = *Candidate;
return true;
}
@@ -1457,30 +1525,30 @@ bool clang::driver::findMIPSMultilibs(const Driver &D,
llvm::Triple::ArchType TargetArch = TargetTriple.getArch();
Multilib::flags_list Flags;
- addMultilibFlag(TargetTriple.isMIPS32(), "m32", Flags);
- addMultilibFlag(TargetTriple.isMIPS64(), "m64", Flags);
- addMultilibFlag(isMips16(Args), "mips16", Flags);
- addMultilibFlag(CPUName == "mips32", "march=mips32", Flags);
+ addMultilibFlag(TargetTriple.isMIPS32(), "-m32", Flags);
+ addMultilibFlag(TargetTriple.isMIPS64(), "-m64", Flags);
+ addMultilibFlag(isMips16(Args), "-mips16", Flags);
+ addMultilibFlag(CPUName == "mips32", "-march=mips32", Flags);
addMultilibFlag(CPUName == "mips32r2" || CPUName == "mips32r3" ||
CPUName == "mips32r5" || CPUName == "p5600",
- "march=mips32r2", Flags);
- addMultilibFlag(CPUName == "mips32r6", "march=mips32r6", Flags);
- addMultilibFlag(CPUName == "mips64", "march=mips64", Flags);
+ "-march=mips32r2", Flags);
+ addMultilibFlag(CPUName == "mips32r6", "-march=mips32r6", Flags);
+ addMultilibFlag(CPUName == "mips64", "-march=mips64", Flags);
addMultilibFlag(CPUName == "mips64r2" || CPUName == "mips64r3" ||
CPUName == "mips64r5" || CPUName == "octeon" ||
CPUName == "octeon+",
- "march=mips64r2", Flags);
- 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",
+ "-march=mips64r2", Flags);
+ addMultilibFlag(CPUName == "mips64r6", "-march=mips64r6", Flags);
+ addMultilibFlag(isMicroMips(Args), "-mmicromips", Flags);
+ addMultilibFlag(tools::mips::isUCLibc(Args), "-muclibc", Flags);
+ addMultilibFlag(tools::mips::isNaN2008(D, Args, TargetTriple), "-mnan=2008",
Flags);
- addMultilibFlag(ABIName == "n32", "mabi=n32", Flags);
- addMultilibFlag(ABIName == "n64", "mabi=n64", Flags);
- addMultilibFlag(isSoftFloatABI(Args), "msoft-float", Flags);
- addMultilibFlag(!isSoftFloatABI(Args), "mhard-float", Flags);
- addMultilibFlag(isMipsEL(TargetArch), "EL", Flags);
- addMultilibFlag(!isMipsEL(TargetArch), "EB", Flags);
+ addMultilibFlag(ABIName == "n32", "-mabi=n32", Flags);
+ addMultilibFlag(ABIName == "n64", "-mabi=n64", Flags);
+ addMultilibFlag(isSoftFloatABI(Args), "-msoft-float", Flags);
+ addMultilibFlag(!isSoftFloatABI(Args), "-mhard-float", Flags);
+ addMultilibFlag(isMipsEL(TargetArch), "-EL", Flags);
+ addMultilibFlag(!isMipsEL(TargetArch), "-EB", Flags);
if (TargetTriple.isAndroid())
return findMipsAndroidMultilibs(D.getVFS(), Path, Flags, NonExistent,
@@ -1509,7 +1577,7 @@ bool clang::driver::findMIPSMultilibs(const Driver &D,
Result.Multilibs.push_back(Default);
Result.Multilibs.FilterOut(NonExistent);
- if (Result.Multilibs.select(Flags, Result.SelectedMultilib)) {
+ if (Result.Multilibs.select(Flags, Result.SelectedMultilibs)) {
Result.BiarchSibling = Multilib();
return true;
}
@@ -1523,22 +1591,23 @@ static void findAndroidArmMultilibs(const Driver &D,
DetectedMultilibs &Result) {
// Find multilibs with subdirectories like armv7-a, thumb, armv7-a/thumb.
FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
- Multilib ArmV7Multilib = makeMultilib("/armv7-a")
- .flag("+march=armv7-a")
- .flag("-mthumb");
- Multilib ThumbMultilib = makeMultilib("/thumb")
- .flag("-march=armv7-a")
- .flag("+mthumb");
- Multilib ArmV7ThumbMultilib = makeMultilib("/armv7-a/thumb")
- .flag("+march=armv7-a")
- .flag("+mthumb");
- Multilib DefaultMultilib = makeMultilib("")
- .flag("-march=armv7-a")
- .flag("-mthumb");
+ MultilibBuilder ArmV7Multilib = MultilibBuilder("/armv7-a")
+ .flag("-march=armv7-a")
+ .flag("-mthumb", /*Disallow=*/true);
+ MultilibBuilder ThumbMultilib = MultilibBuilder("/thumb")
+ .flag("-march=armv7-a", /*Disallow=*/true)
+ .flag("-mthumb");
+ MultilibBuilder ArmV7ThumbMultilib =
+ MultilibBuilder("/armv7-a/thumb").flag("-march=armv7-a").flag("-mthumb");
+ MultilibBuilder DefaultMultilib =
+ MultilibBuilder("")
+ .flag("-march=armv7-a", /*Disallow=*/true)
+ .flag("-mthumb", /*Disallow=*/true);
MultilibSet AndroidArmMultilibs =
- MultilibSet()
- .Either(ThumbMultilib, ArmV7Multilib,
- ArmV7ThumbMultilib, DefaultMultilib)
+ MultilibSetBuilder()
+ .Either(ThumbMultilib, ArmV7Multilib, ArmV7ThumbMultilib,
+ DefaultMultilib)
+ .makeMultilibSet()
.FilterOut(NonExistent);
Multilib::flags_list Flags;
@@ -1552,10 +1621,10 @@ static void findAndroidArmMultilibs(const Driver &D,
bool IsArmV7Mode = (IsArmArch || IsThumbArch) &&
(llvm::ARM::parseArchVersion(Arch) == 7 ||
(IsArmArch && Arch == "" && IsV7SubArch));
- addMultilibFlag(IsArmV7Mode, "march=armv7-a", Flags);
- addMultilibFlag(IsThumbMode, "mthumb", Flags);
+ addMultilibFlag(IsArmV7Mode, "-march=armv7-a", Flags);
+ addMultilibFlag(IsThumbMode, "-mthumb", Flags);
- if (AndroidArmMultilibs.select(Flags, Result.SelectedMultilib))
+ if (AndroidArmMultilibs.select(Flags, Result.SelectedMultilibs))
Result.Multilibs = AndroidArmMultilibs;
}
@@ -1564,24 +1633,210 @@ static bool findMSP430Multilibs(const Driver &D,
StringRef Path, const ArgList &Args,
DetectedMultilibs &Result) {
FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
- Multilib WithoutExceptions = makeMultilib("/430").flag("-exceptions");
- Multilib WithExceptions = makeMultilib("/430/exceptions").flag("+exceptions");
+ MultilibBuilder WithoutExceptions =
+ MultilibBuilder("/430").flag("-exceptions", /*Disallow=*/true);
+ MultilibBuilder WithExceptions =
+ MultilibBuilder("/430/exceptions").flag("-exceptions");
// FIXME: when clang starts to support msp430x ISA additional logic
// to select between multilib must be implemented
- // Multilib MSP430xMultilib = makeMultilib("/large");
+ // MultilibBuilder MSP430xMultilib = MultilibBuilder("/large");
- Result.Multilibs.push_back(WithoutExceptions);
- Result.Multilibs.push_back(WithExceptions);
+ Result.Multilibs.push_back(WithoutExceptions.makeMultilib());
+ Result.Multilibs.push_back(WithExceptions.makeMultilib());
Result.Multilibs.FilterOut(NonExistent);
Multilib::flags_list Flags;
addMultilibFlag(Args.hasFlag(options::OPT_fexceptions,
options::OPT_fno_exceptions, false),
- "exceptions", Flags);
- if (Result.Multilibs.select(Flags, Result.SelectedMultilib))
+ "-exceptions", Flags);
+ if (Result.Multilibs.select(Flags, Result.SelectedMultilibs))
+ return true;
+
+ return false;
+}
+
+static void findCSKYMultilibs(const Driver &D, const llvm::Triple &TargetTriple,
+ StringRef Path, const ArgList &Args,
+ DetectedMultilibs &Result) {
+ FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
+
+ tools::csky::FloatABI TheFloatABI = tools::csky::getCSKYFloatABI(D, Args);
+ std::optional<llvm::StringRef> Res =
+ tools::csky::getCSKYArchName(D, Args, TargetTriple);
+
+ if (!Res)
+ return;
+ auto ARCHName = *Res;
+
+ Multilib::flags_list Flags;
+ addMultilibFlag(TheFloatABI == tools::csky::FloatABI::Hard, "-hard-fp",
+ Flags);
+ addMultilibFlag(TheFloatABI == tools::csky::FloatABI::SoftFP, "-soft-fp",
+ Flags);
+ addMultilibFlag(TheFloatABI == tools::csky::FloatABI::Soft, "-soft", Flags);
+ addMultilibFlag(ARCHName == "ck801", "-march=ck801", Flags);
+ addMultilibFlag(ARCHName == "ck802", "-march=ck802", Flags);
+ addMultilibFlag(ARCHName == "ck803", "-march=ck803", Flags);
+ addMultilibFlag(ARCHName == "ck804", "-march=ck804", Flags);
+ addMultilibFlag(ARCHName == "ck805", "-march=ck805", Flags);
+ addMultilibFlag(ARCHName == "ck807", "-march=ck807", Flags);
+ addMultilibFlag(ARCHName == "ck810", "-march=ck810", Flags);
+ addMultilibFlag(ARCHName == "ck810v", "-march=ck810v", Flags);
+ addMultilibFlag(ARCHName == "ck860", "-march=ck860", Flags);
+ addMultilibFlag(ARCHName == "ck860v", "-march=ck860v", Flags);
+
+ bool isBigEndian = false;
+ if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
+ options::OPT_mbig_endian))
+ isBigEndian = !A->getOption().matches(options::OPT_mlittle_endian);
+ addMultilibFlag(isBigEndian, "-EB", Flags);
+
+ auto HardFloat = MultilibBuilder("/hard-fp").flag("-hard-fp");
+ auto SoftFpFloat = MultilibBuilder("/soft-fp").flag("-soft-fp");
+ auto SoftFloat = MultilibBuilder("").flag("-soft");
+ auto Arch801 = MultilibBuilder("/ck801").flag("-march=ck801");
+ auto Arch802 = MultilibBuilder("/ck802").flag("-march=ck802");
+ auto Arch803 = MultilibBuilder("/ck803").flag("-march=ck803");
+ // CK804 use the same library as CK803
+ auto Arch804 = MultilibBuilder("/ck803").flag("-march=ck804");
+ auto Arch805 = MultilibBuilder("/ck805").flag("-march=ck805");
+ auto Arch807 = MultilibBuilder("/ck807").flag("-march=ck807");
+ auto Arch810 = MultilibBuilder("").flag("-march=ck810");
+ auto Arch810v = MultilibBuilder("/ck810v").flag("-march=ck810v");
+ auto Arch860 = MultilibBuilder("/ck860").flag("-march=ck860");
+ auto Arch860v = MultilibBuilder("/ck860v").flag("-march=ck860v");
+ auto BigEndian = MultilibBuilder("/big").flag("-EB");
+
+ MultilibSet CSKYMultilibs =
+ MultilibSetBuilder()
+ .Maybe(BigEndian)
+ .Either({Arch801, Arch802, Arch803, Arch804, Arch805, Arch807,
+ Arch810, Arch810v, Arch860, Arch860v})
+ .Either(HardFloat, SoftFpFloat, SoftFloat)
+ .makeMultilibSet()
+ .FilterOut(NonExistent);
+
+ if (CSKYMultilibs.select(Flags, Result.SelectedMultilibs))
+ Result.Multilibs = CSKYMultilibs;
+}
+
+/// Extend the multi-lib re-use selection mechanism for RISC-V.
+/// This function will try to re-use multi-lib if they are compatible.
+/// Definition of compatible:
+/// - ABI must be the same.
+/// - multi-lib is a subset of current arch, e.g. multi-lib=march=rv32im
+/// is a subset of march=rv32imc.
+/// - march that contains atomic extension can't reuse multi-lib that
+/// doesn't have atomic, vice versa. e.g. multi-lib=march=rv32im and
+/// march=rv32ima are not compatible, because software and hardware
+/// atomic operation can't work together correctly.
+static bool
+selectRISCVMultilib(const MultilibSet &RISCVMultilibSet, StringRef Arch,
+ const Multilib::flags_list &Flags,
+ llvm::SmallVectorImpl<Multilib> &SelectedMultilibs) {
+ // Try to find the perfect matching multi-lib first.
+ if (RISCVMultilibSet.select(Flags, SelectedMultilibs))
return true;
+ Multilib::flags_list NewFlags;
+ std::vector<MultilibBuilder> NewMultilibs;
+
+ llvm::Expected<std::unique_ptr<llvm::RISCVISAInfo>> ParseResult =
+ llvm::RISCVISAInfo::parseArchString(
+ Arch, /*EnableExperimentalExtension=*/true,
+ /*ExperimentalExtensionVersionCheck=*/false);
+ // Ignore any error here, we assume it will be handled in another place.
+ if (llvm::errorToBool(ParseResult.takeError()))
+ return false;
+
+ auto &ISAInfo = *ParseResult;
+
+ addMultilibFlag(ISAInfo->getXLen() == 32, "-m32", NewFlags);
+ addMultilibFlag(ISAInfo->getXLen() == 64, "-m64", NewFlags);
+
+ // Collect all flags except march=*
+ for (StringRef Flag : Flags) {
+ if (Flag.starts_with("!march=") || Flag.starts_with("-march="))
+ continue;
+
+ NewFlags.push_back(Flag.str());
+ }
+
+ llvm::StringSet<> AllArchExts;
+ // Reconstruct multi-lib list, and break march option into separated
+ // extension. e.g. march=rv32im -> +i +m
+ for (const auto &M : RISCVMultilibSet) {
+ bool Skip = false;
+
+ MultilibBuilder NewMultilib =
+ MultilibBuilder(M.gccSuffix(), M.osSuffix(), M.includeSuffix());
+ for (StringRef Flag : M.flags()) {
+ // Add back all flags except -march.
+ if (!Flag.consume_front("-march=")) {
+ NewMultilib.flag(Flag);
+ continue;
+ }
+
+ // Break down -march into individual extension.
+ llvm::Expected<std::unique_ptr<llvm::RISCVISAInfo>> MLConfigParseResult =
+ llvm::RISCVISAInfo::parseArchString(
+ Flag, /*EnableExperimentalExtension=*/true,
+ /*ExperimentalExtensionVersionCheck=*/false);
+ // Ignore any error here, we assume it will handled in another place.
+ if (llvm::errorToBool(MLConfigParseResult.takeError())) {
+ // We might get a parsing error if rv32e in the list, we could just skip
+ // that and process the rest of multi-lib configs.
+ Skip = true;
+ continue;
+ }
+ auto &MLConfigISAInfo = *MLConfigParseResult;
+
+ const llvm::RISCVISAInfo::OrderedExtensionMap &MLConfigArchExts =
+ MLConfigISAInfo->getExtensions();
+ for (auto MLConfigArchExt : MLConfigArchExts) {
+ auto ExtName = MLConfigArchExt.first;
+ NewMultilib.flag(Twine("-", ExtName).str());
+
+ if (AllArchExts.insert(ExtName).second) {
+ addMultilibFlag(ISAInfo->hasExtension(ExtName),
+ Twine("-", ExtName).str(), NewFlags);
+ }
+ }
+
+ // Check the XLEN explicitly.
+ if (MLConfigISAInfo->getXLen() == 32) {
+ NewMultilib.flag("-m32");
+ NewMultilib.flag("-m64", /*Disallow*/ true);
+ } else {
+ NewMultilib.flag("-m32", /*Disallow*/ true);
+ NewMultilib.flag("-m64");
+ }
+
+ // Atomic extension must be explicitly checked, soft and hard atomic
+ // operation never co-work correctly.
+ if (!MLConfigISAInfo->hasExtension("a"))
+ NewMultilib.flag("-a", /*Disallow*/ true);
+ }
+
+ if (Skip)
+ continue;
+
+ NewMultilibs.emplace_back(NewMultilib);
+ }
+
+ // Build an internal used only multi-lib list, used for checking any
+ // compatible multi-lib.
+ MultilibSet NewRISCVMultilibs =
+ MultilibSetBuilder().Either(NewMultilibs).makeMultilibSet();
+
+ if (NewRISCVMultilibs.select(NewFlags, SelectedMultilibs))
+ for (const Multilib &NewSelectedM : SelectedMultilibs)
+ for (const auto &M : RISCVMultilibSet)
+ // Look up the corresponding multi-lib entry in original multi-lib set.
+ if (M.gccSuffix() == NewSelectedM.gccSuffix())
+ return true;
+
return false;
}
@@ -1601,17 +1856,19 @@ static void findRISCVBareMetalMultilibs(const Driver &D,
{"rv32imac", "ilp32"}, {"rv32imafc", "ilp32f"}, {"rv64imac", "lp64"},
{"rv64imafdc", "lp64d"}};
- std::vector<Multilib> Ms;
+ std::vector<MultilibBuilder> Ms;
for (auto Element : RISCVMultilibSet) {
// multilib path rule is ${march}/${mabi}
Ms.emplace_back(
- makeMultilib((Twine(Element.march) + "/" + Twine(Element.mabi)).str())
- .flag(Twine("+march=", Element.march).str())
- .flag(Twine("+mabi=", Element.mabi).str()));
+ MultilibBuilder(
+ (Twine(Element.march) + "/" + Twine(Element.mabi)).str())
+ .flag(Twine("-march=", Element.march).str())
+ .flag(Twine("-mabi=", Element.mabi).str()));
}
MultilibSet RISCVMultilibs =
- MultilibSet()
- .Either(ArrayRef<Multilib>(Ms))
+ MultilibSetBuilder()
+ .Either(Ms)
+ .makeMultilibSet()
.FilterOut(NonExistent)
.setFilePathsCallback([](const Multilib &M) {
return std::vector<std::string>(
@@ -1620,22 +1877,22 @@ static void findRISCVBareMetalMultilibs(const Driver &D,
"/../../../../riscv32-unknown-elf/lib" + M.gccSuffix()});
});
-
Multilib::flags_list Flags;
llvm::StringSet<> Added_ABIs;
StringRef ABIName = tools::riscv::getRISCVABI(Args, TargetTriple);
StringRef MArch = tools::riscv::getRISCVArch(Args, TargetTriple);
for (auto Element : RISCVMultilibSet) {
addMultilibFlag(MArch == Element.march,
- Twine("march=", Element.march).str().c_str(), Flags);
+ Twine("-march=", Element.march).str().c_str(), Flags);
if (!Added_ABIs.count(Element.mabi)) {
Added_ABIs.insert(Element.mabi);
addMultilibFlag(ABIName == Element.mabi,
- Twine("mabi=", Element.mabi).str().c_str(), Flags);
+ Twine("-mabi=", Element.mabi).str().c_str(), Flags);
}
}
- if (RISCVMultilibs.select(Flags, Result.SelectedMultilib))
+ if (selectRISCVMultilib(RISCVMultilibs, MArch, Flags,
+ Result.SelectedMultilibs))
Result.Multilibs = RISCVMultilibs;
}
@@ -1646,33 +1903,38 @@ static void findRISCVMultilibs(const Driver &D,
return findRISCVBareMetalMultilibs(D, TargetTriple, Path, Args, Result);
FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
- Multilib Ilp32 = makeMultilib("lib32/ilp32").flag("+m32").flag("+mabi=ilp32");
- Multilib Ilp32f =
- makeMultilib("lib32/ilp32f").flag("+m32").flag("+mabi=ilp32f");
- Multilib Ilp32d =
- makeMultilib("lib32/ilp32d").flag("+m32").flag("+mabi=ilp32d");
- Multilib Lp64 = makeMultilib("lib64/lp64").flag("+m64").flag("+mabi=lp64");
- Multilib Lp64f = makeMultilib("lib64/lp64f").flag("+m64").flag("+mabi=lp64f");
- Multilib Lp64d = makeMultilib("lib64/lp64d").flag("+m64").flag("+mabi=lp64d");
+ MultilibBuilder Ilp32 =
+ MultilibBuilder("lib32/ilp32").flag("-m32").flag("-mabi=ilp32");
+ MultilibBuilder Ilp32f =
+ MultilibBuilder("lib32/ilp32f").flag("-m32").flag("-mabi=ilp32f");
+ MultilibBuilder Ilp32d =
+ MultilibBuilder("lib32/ilp32d").flag("-m32").flag("-mabi=ilp32d");
+ MultilibBuilder Lp64 =
+ MultilibBuilder("lib64/lp64").flag("-m64").flag("-mabi=lp64");
+ MultilibBuilder Lp64f =
+ MultilibBuilder("lib64/lp64f").flag("-m64").flag("-mabi=lp64f");
+ MultilibBuilder Lp64d =
+ MultilibBuilder("lib64/lp64d").flag("-m64").flag("-mabi=lp64d");
MultilibSet RISCVMultilibs =
- MultilibSet()
+ MultilibSetBuilder()
.Either({Ilp32, Ilp32f, Ilp32d, Lp64, Lp64f, Lp64d})
+ .makeMultilibSet()
.FilterOut(NonExistent);
Multilib::flags_list Flags;
bool IsRV64 = TargetTriple.getArch() == llvm::Triple::riscv64;
StringRef ABIName = tools::riscv::getRISCVABI(Args, TargetTriple);
- addMultilibFlag(!IsRV64, "m32", Flags);
- addMultilibFlag(IsRV64, "m64", Flags);
- addMultilibFlag(ABIName == "ilp32", "mabi=ilp32", Flags);
- addMultilibFlag(ABIName == "ilp32f", "mabi=ilp32f", Flags);
- addMultilibFlag(ABIName == "ilp32d", "mabi=ilp32d", Flags);
- addMultilibFlag(ABIName == "lp64", "mabi=lp64", Flags);
- addMultilibFlag(ABIName == "lp64f", "mabi=lp64f", Flags);
- addMultilibFlag(ABIName == "lp64d", "mabi=lp64d", Flags);
+ addMultilibFlag(!IsRV64, "-m32", Flags);
+ addMultilibFlag(IsRV64, "-m64", Flags);
+ addMultilibFlag(ABIName == "ilp32", "-mabi=ilp32", Flags);
+ addMultilibFlag(ABIName == "ilp32f", "-mabi=ilp32f", Flags);
+ addMultilibFlag(ABIName == "ilp32d", "-mabi=ilp32d", Flags);
+ addMultilibFlag(ABIName == "lp64", "-mabi=lp64", Flags);
+ addMultilibFlag(ABIName == "lp64f", "-mabi=lp64f", Flags);
+ addMultilibFlag(ABIName == "lp64d", "-mabi=lp64d", Flags);
- if (RISCVMultilibs.select(Flags, Result.SelectedMultilib))
+ if (RISCVMultilibs.select(Flags, Result.SelectedMultilibs))
Result.Multilibs = RISCVMultilibs;
}
@@ -1681,7 +1943,7 @@ static bool findBiarchMultilibs(const Driver &D,
StringRef Path, const ArgList &Args,
bool NeedsBiarchSuffix,
DetectedMultilibs &Result) {
- Multilib Default;
+ MultilibBuilder DefaultBuilder;
// Some versions of SUSE and Fedora on ppc64 put 32-bit libs
// in what would normally be GCCInstallPath and put the 64-bit
@@ -1692,7 +1954,7 @@ static bool findBiarchMultilibs(const Driver &D,
StringRef Suff64 = "/64";
// Solaris uses platform-specific suffixes instead of /64.
- if (TargetTriple.getOS() == llvm::Triple::Solaris) {
+ if (TargetTriple.isOSSolaris()) {
switch (TargetTriple.getArch()) {
case llvm::Triple::x86:
case llvm::Triple::x86_64:
@@ -1707,24 +1969,33 @@ static bool findBiarchMultilibs(const Driver &D,
}
}
- Multilib Alt64 = Multilib()
+ Multilib Alt64 = MultilibBuilder()
.gccSuffix(Suff64)
.includeSuffix(Suff64)
- .flag("-m32")
- .flag("+m64")
- .flag("-mx32");
- Multilib Alt32 = Multilib()
+ .flag("-m32", /*Disallow=*/true)
+ .flag("-m64")
+ .flag("-mx32", /*Disallow=*/true)
+ .makeMultilib();
+ Multilib Alt32 = MultilibBuilder()
.gccSuffix("/32")
.includeSuffix("/32")
- .flag("+m32")
- .flag("-m64")
- .flag("-mx32");
- Multilib Altx32 = Multilib()
+ .flag("-m32")
+ .flag("-m64", /*Disallow=*/true)
+ .flag("-mx32", /*Disallow=*/true)
+ .makeMultilib();
+ Multilib Altx32 = MultilibBuilder()
.gccSuffix("/x32")
.includeSuffix("/x32")
- .flag("-m32")
- .flag("-m64")
- .flag("+mx32");
+ .flag("-m32", /*Disallow=*/true)
+ .flag("-m64", /*Disallow=*/true)
+ .flag("-mx32")
+ .makeMultilib();
+ Multilib Alt32sparc = MultilibBuilder()
+ .gccSuffix("/sparcv8plus")
+ .includeSuffix("/sparcv8plus")
+ .flag("-m32")
+ .flag("-m64", /*Disallow=*/true)
+ .makeMultilib();
// GCC toolchain for IAMCU doesn't have crtbegin.o, so look for libgcc.a.
FilterNonExistent NonExistent(
@@ -1736,10 +2007,14 @@ static bool findBiarchMultilibs(const Driver &D,
const bool IsX32 = TargetTriple.isX32();
if (TargetTriple.isArch32Bit() && !NonExistent(Alt32))
Want = WANT64;
+ if (TargetTriple.isArch32Bit() && !NonExistent(Alt32sparc))
+ Want = WANT64;
else if (TargetTriple.isArch64Bit() && IsX32 && !NonExistent(Altx32))
Want = WANT64;
else if (TargetTriple.isArch64Bit() && !IsX32 && !NonExistent(Alt64))
Want = WANT32;
+ else if (TargetTriple.isArch64Bit() && !NonExistent(Alt32sparc))
+ Want = WANT64;
else {
if (TargetTriple.isArch32Bit())
Want = NeedsBiarchSuffix ? WANT64 : WANT32;
@@ -1750,31 +2025,42 @@ static bool findBiarchMultilibs(const Driver &D,
}
if (Want == WANT32)
- Default.flag("+m32").flag("-m64").flag("-mx32");
+ DefaultBuilder.flag("-m32")
+ .flag("-m64", /*Disallow=*/true)
+ .flag("-mx32", /*Disallow=*/true);
else if (Want == WANT64)
- Default.flag("-m32").flag("+m64").flag("-mx32");
+ DefaultBuilder.flag("-m32", /*Disallow=*/true)
+ .flag("-m64")
+ .flag("-mx32", /*Disallow=*/true);
else if (Want == WANTX32)
- Default.flag("-m32").flag("-m64").flag("+mx32");
+ DefaultBuilder.flag("-m32", /*Disallow=*/true)
+ .flag("-m64", /*Disallow=*/true)
+ .flag("-mx32");
else
return false;
+ Multilib Default = DefaultBuilder.makeMultilib();
+
Result.Multilibs.push_back(Default);
Result.Multilibs.push_back(Alt64);
Result.Multilibs.push_back(Alt32);
Result.Multilibs.push_back(Altx32);
+ Result.Multilibs.push_back(Alt32sparc);
Result.Multilibs.FilterOut(NonExistent);
Multilib::flags_list Flags;
- addMultilibFlag(TargetTriple.isArch64Bit() && !IsX32, "m64", Flags);
- addMultilibFlag(TargetTriple.isArch32Bit(), "m32", Flags);
- addMultilibFlag(TargetTriple.isArch64Bit() && IsX32, "mx32", Flags);
+ addMultilibFlag(TargetTriple.isArch64Bit() && !IsX32, "-m64", Flags);
+ addMultilibFlag(TargetTriple.isArch32Bit(), "-m32", Flags);
+ addMultilibFlag(TargetTriple.isArch64Bit() && IsX32, "-mx32", Flags);
- if (!Result.Multilibs.select(Flags, Result.SelectedMultilib))
+ if (!Result.Multilibs.select(Flags, Result.SelectedMultilibs))
return false;
- if (Result.SelectedMultilib == Alt64 || Result.SelectedMultilib == Alt32 ||
- Result.SelectedMultilib == Altx32)
+ if (Result.SelectedMultilibs.back() == Alt64 ||
+ Result.SelectedMultilibs.back() == Alt32 ||
+ Result.SelectedMultilibs.back() == Altx32 ||
+ Result.SelectedMultilibs.back() == Alt32sparc)
Result.BiarchSibling = Default;
return true;
@@ -1790,8 +2076,15 @@ bool Generic_GCC::GCCVersion::isOlderThan(int RHSMajor, int RHSMinor,
StringRef RHSPatchSuffix) const {
if (Major != RHSMajor)
return Major < RHSMajor;
- if (Minor != RHSMinor)
+ if (Minor != RHSMinor) {
+ // Note that versions without a specified minor sort higher than those with
+ // a minor.
+ if (RHSMinor == -1)
+ return true;
+ if (Minor == -1)
+ return false;
return Minor < RHSMinor;
+ }
if (Patch != RHSPatch) {
// Note that versions without a specified patch sort higher than those with
// a patch.
@@ -1827,45 +2120,72 @@ Generic_GCC::GCCVersion Generic_GCC::GCCVersion::Parse(StringRef VersionText) {
std::pair<StringRef, StringRef> First = VersionText.split('.');
std::pair<StringRef, StringRef> Second = First.second.split('.');
- GCCVersion GoodVersion = {VersionText.str(), -1, -1, -1, "", "", ""};
- if (First.first.getAsInteger(10, GoodVersion.Major) || GoodVersion.Major < 0)
- return BadVersion;
- GoodVersion.MajorStr = First.first.str();
- if (First.second.empty())
- return GoodVersion;
+ StringRef MajorStr = First.first;
StringRef MinorStr = Second.first;
- if (Second.second.empty()) {
- if (size_t EndNumber = MinorStr.find_first_not_of("0123456789")) {
- GoodVersion.PatchSuffix = std::string(MinorStr.substr(EndNumber));
- MinorStr = MinorStr.slice(0, EndNumber);
- }
- }
- if (MinorStr.getAsInteger(10, GoodVersion.Minor) || GoodVersion.Minor < 0)
- return BadVersion;
- GoodVersion.MinorStr = MinorStr.str();
+ StringRef PatchStr = Second.second;
- // First look for a number prefix and parse that if present. Otherwise just
- // stash the entire patch string in the suffix, and leave the number
- // unspecified. This covers versions strings such as:
- // 5 (handled above)
+ GCCVersion GoodVersion = {VersionText.str(), -1, -1, -1, "", "", ""};
+
+ // Parse version number strings such as:
+ // 5
// 4.4
// 4.4-patched
// 4.4.0
// 4.4.x
// 4.4.2-rc4
// 4.4.x-patched
- // And retains any patch number it finds.
- StringRef PatchText = Second.second;
- if (!PatchText.empty()) {
- if (size_t EndNumber = PatchText.find_first_not_of("0123456789")) {
- // Try to parse the number and any suffix.
- if (PatchText.slice(0, EndNumber).getAsInteger(10, GoodVersion.Patch) ||
- GoodVersion.Patch < 0)
- return BadVersion;
- GoodVersion.PatchSuffix = std::string(PatchText.substr(EndNumber));
+ // 10-win32
+ // Split on '.', handle 1, 2 or 3 such segments. Each segment must contain
+ // purely a number, except for the last one, where a non-number suffix
+ // is stored in PatchSuffix. The third segment is allowed to not contain
+ // a number at all.
+
+ auto TryParseLastNumber = [&](StringRef Segment, int &Number,
+ std::string &OutStr) -> bool {
+ // Look for a number prefix and parse that, and split out any trailing
+ // string into GoodVersion.PatchSuffix.
+
+ if (size_t EndNumber = Segment.find_first_not_of("0123456789")) {
+ StringRef NumberStr = Segment.slice(0, EndNumber);
+ if (NumberStr.getAsInteger(10, Number) || Number < 0)
+ return false;
+ OutStr = NumberStr;
+ GoodVersion.PatchSuffix = Segment.substr(EndNumber);
+ return true;
}
+ return false;
+ };
+ auto TryParseNumber = [](StringRef Segment, int &Number) -> bool {
+ if (Segment.getAsInteger(10, Number) || Number < 0)
+ return false;
+ return true;
+ };
+
+ if (MinorStr.empty()) {
+ // If no minor string, major is the last segment
+ if (!TryParseLastNumber(MajorStr, GoodVersion.Major, GoodVersion.MajorStr))
+ return BadVersion;
+ return GoodVersion;
+ }
+
+ if (!TryParseNumber(MajorStr, GoodVersion.Major))
+ return BadVersion;
+ GoodVersion.MajorStr = MajorStr;
+
+ if (PatchStr.empty()) {
+ // If no patch string, minor is the last segment
+ if (!TryParseLastNumber(MinorStr, GoodVersion.Minor, GoodVersion.MinorStr))
+ return BadVersion;
+ return GoodVersion;
}
+ if (!TryParseNumber(MinorStr, GoodVersion.Minor))
+ return BadVersion;
+ GoodVersion.MinorStr = MinorStr;
+
+ // For the last segment, tolerate a missing number.
+ std::string DummyStr;
+ TryParseLastNumber(PatchStr, GoodVersion.Patch, DummyStr);
return GoodVersion;
}
@@ -1894,8 +2214,7 @@ static llvm::StringRef getGCCToolchainDir(const ArgList &Args,
/// necessary because the driver doesn't store the final version of the target
/// triple.
void Generic_GCC::GCCInstallationDetector::init(
- const llvm::Triple &TargetTriple, const ArgList &Args,
- ArrayRef<std::string> ExtraTripleAliases) {
+ const llvm::Triple &TargetTriple, const ArgList &Args) {
llvm::Triple BiarchVariantTriple = TargetTriple.isArch32Bit()
? TargetTriple.get64BitArchVariant()
: TargetTriple.get32BitArchVariant();
@@ -1904,10 +2223,48 @@ void Generic_GCC::GCCInstallationDetector::init(
// The compatible GCC triples for this particular architecture.
SmallVector<StringRef, 16> CandidateTripleAliases;
SmallVector<StringRef, 16> CandidateBiarchTripleAliases;
+ // Add some triples that we want to check first.
+ CandidateTripleAliases.push_back(TargetTriple.str());
+ std::string TripleNoVendor = TargetTriple.getArchName().str() + "-" +
+ TargetTriple.getOSAndEnvironmentName().str();
+ if (TargetTriple.getVendor() == llvm::Triple::UnknownVendor)
+ CandidateTripleAliases.push_back(TripleNoVendor);
+
CollectLibDirsAndTriples(TargetTriple, BiarchVariantTriple, CandidateLibDirs,
CandidateTripleAliases, CandidateBiarchLibDirs,
CandidateBiarchTripleAliases);
+ // If --gcc-install-dir= is specified, skip filesystem detection.
+ if (const Arg *A =
+ Args.getLastArg(clang::driver::options::OPT_gcc_install_dir_EQ);
+ A && A->getValue()[0]) {
+ StringRef InstallDir = A->getValue();
+ if (!ScanGCCForMultilibs(TargetTriple, Args, InstallDir, false)) {
+ D.Diag(diag::err_drv_invalid_gcc_install_dir) << InstallDir;
+ } else {
+ (void)InstallDir.consume_back("/");
+ StringRef VersionText = llvm::sys::path::filename(InstallDir);
+ StringRef TripleText =
+ llvm::sys::path::filename(llvm::sys::path::parent_path(InstallDir));
+
+ Version = GCCVersion::Parse(VersionText);
+ GCCTriple.setTriple(TripleText);
+ GCCInstallPath = std::string(InstallDir);
+ GCCParentLibPath = GCCInstallPath + "/../../..";
+ IsValid = true;
+ }
+ return;
+ }
+
+ // If --gcc-triple is specified use this instead of trying to
+ // auto-detect a triple.
+ if (const Arg *A =
+ Args.getLastArg(clang::driver::options::OPT_gcc_triple_EQ)) {
+ StringRef GCCTriple = A->getValue();
+ CandidateTripleAliases.clear();
+ CandidateTripleAliases.push_back(GCCTriple);
+ }
+
// Compute the set of prefixes for our search.
SmallVector<std::string, 8> Prefixes;
StringRef GCCToolchainDir = getGCCToolchainDir(Args, D.SysRoot);
@@ -1943,9 +2300,6 @@ void Generic_GCC::GCCInstallationDetector::init(
// may pick the libraries for x86_64-pc-linux-gnu even when exact matching
// triple x86_64-gentoo-linux-gnu is present.
GentooTestTriples.push_back(TargetTriple.str());
- // Check rest of triples.
- GentooTestTriples.append(ExtraTripleAliases.begin(),
- ExtraTripleAliases.end());
GentooTestTriples.append(CandidateTripleAliases.begin(),
CandidateTripleAliases.end());
if (ScanGentooConfigs(TargetTriple, Args, GentooTestTriples,
@@ -1962,19 +2316,12 @@ void Generic_GCC::GCCInstallationDetector::init(
if (!VFS.exists(Prefix))
continue;
for (StringRef Suffix : CandidateLibDirs) {
- const std::string LibDir = Prefix + Suffix.str();
+ const std::string LibDir = concat(Prefix, Suffix);
if (!VFS.exists(LibDir))
continue;
// Maybe filter out <libdir>/gcc and <libdir>/gcc-cross.
bool GCCDirExists = VFS.exists(LibDir + "/gcc");
bool GCCCrossDirExists = VFS.exists(LibDir + "/gcc-cross");
- // Try to match the exact target triple first.
- ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, TargetTriple.str(),
- false, GCCDirExists, GCCCrossDirExists);
- // Try rest of possible triples.
- for (StringRef Candidate : ExtraTripleAliases) // Try these first.
- ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate, false,
- GCCDirExists, GCCCrossDirExists);
for (StringRef Candidate : CandidateTripleAliases)
ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate, false,
GCCDirExists, GCCCrossDirExists);
@@ -2011,8 +2358,8 @@ void Generic_GCC::GCCInstallationDetector::print(raw_ostream &OS) const {
}
bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
- if (BiarchSibling.hasValue()) {
- M = BiarchSibling.getValue();
+ if (BiarchSibling) {
+ M = *BiarchSibling;
return true;
}
return false;
@@ -2021,14 +2368,21 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
const llvm::Triple &TargetTriple, SmallVectorImpl<std::string> &Prefixes,
StringRef SysRoot) {
- if (TargetTriple.getOS() == llvm::Triple::Solaris) {
+
+ if (TargetTriple.isOSHaiku()) {
+ Prefixes.push_back(concat(SysRoot, "/boot/system/develop/tools"));
+ return;
+ }
+
+ if (TargetTriple.isOSSolaris()) {
// Solaris is a special case.
// The GCC installation is under
// /usr/gcc/<major>.<minor>/lib/gcc/<triple>/<major>.<minor>.<patch>/
// so we need to find those /usr/gcc/*/lib/gcc libdirs and go with
// /usr/gcc/<version> as a prefix.
- std::string PrefixDir = SysRoot.str() + "/usr/gcc";
+ SmallVector<std::pair<GCCVersion, std::string>, 8> SolarisPrefixes;
+ std::string PrefixDir = concat(SysRoot, "/usr/gcc");
std::error_code EC;
for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(PrefixDir, EC),
LE;
@@ -2045,14 +2399,27 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
if (!D.getVFS().exists(CandidateLibPath))
continue;
- Prefixes.push_back(CandidatePrefix);
+ SolarisPrefixes.emplace_back(
+ std::make_pair(CandidateVersion, CandidatePrefix));
}
+ // Sort in reverse order so GCCInstallationDetector::init picks the latest.
+ std::sort(SolarisPrefixes.rbegin(), SolarisPrefixes.rend());
+ for (auto p : SolarisPrefixes)
+ Prefixes.emplace_back(p.second);
return;
}
- // Non-Solaris is much simpler - most systems just go with "/usr".
- if (SysRoot.empty() && TargetTriple.getOS() == llvm::Triple::Linux) {
- // Yet, still look for RHEL devtoolsets.
+ // For Linux, if --sysroot is not specified, look for RHEL/CentOS devtoolsets
+ // and gcc-toolsets.
+ if (SysRoot.empty() && TargetTriple.getOS() == llvm::Triple::Linux &&
+ D.getVFS().exists("/opt/rh")) {
+ // TODO: We may want to remove this, since the functionality
+ // can be achieved using config files.
+ Prefixes.push_back("/opt/rh/gcc-toolset-12/root/usr");
+ Prefixes.push_back("/opt/rh/gcc-toolset-11/root/usr");
+ Prefixes.push_back("/opt/rh/gcc-toolset-10/root/usr");
+ Prefixes.push_back("/opt/rh/devtoolset-12/root/usr");
+ Prefixes.push_back("/opt/rh/devtoolset-11/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");
@@ -2062,7 +2429,9 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
Prefixes.push_back("/opt/rh/devtoolset-3/root/usr");
Prefixes.push_back("/opt/rh/devtoolset-2/root/usr");
}
- Prefixes.push_back(SysRoot.str() + "/usr");
+
+ // Fall back to /usr which is used by most non-Solaris systems.
+ Prefixes.push_back(concat(SysRoot, "/usr"));
}
/*static*/ void Generic_GCC::GCCInstallationDetector::CollectLibDirsAndTriples(
@@ -2074,30 +2443,38 @@ 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"};
static const char *const AVRLibDirs[] = {"/lib"};
static const char *const AVRTriples[] = {"avr"};
+ static const char *const CSKYLibDirs[] = {"/lib"};
+ static const char *const CSKYTriples[] = {
+ "csky-linux-gnuabiv2", "csky-linux-uclibcabiv2", "csky-elf-noneabiv2"};
+
static const char *const X86_64LibDirs[] = {"/lib64", "/lib"};
static const char *const X86_64Triples[] = {
"x86_64-linux-gnu", "x86_64-unknown-linux-gnu",
@@ -2105,31 +2482,32 @@ 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",
};
+ static const char *const LoongArch64LibDirs[] = {"/lib64", "/lib"};
+ static const char *const LoongArch64Triples[] = {
+ "loongarch64-linux-gnu", "loongarch64-unknown-linux-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 +2518,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 +2558,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",
@@ -2201,16 +2576,14 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
using std::begin;
using std::end;
- if (TargetTriple.getOS() == llvm::Triple::Solaris) {
+ if (TargetTriple.isOSSolaris()) {
static const char *const SolarisLibDirs[] = {"/lib"};
static const char *const SolarisSparcV8Triples[] = {
- "sparc-sun-solaris2.11", "sparc-sun-solaris2.12"};
+ "sparc-sun-solaris2.11"};
static const char *const SolarisSparcV9Triples[] = {
- "sparcv9-sun-solaris2.11", "sparcv9-sun-solaris2.12"};
- static const char *const SolarisX86Triples[] = {"i386-pc-solaris2.11",
- "i386-pc-solaris2.12"};
- static const char *const SolarisX86_64Triples[] = {"x86_64-pc-solaris2.11",
- "x86_64-pc-solaris2.12"};
+ "sparcv9-sun-solaris2.11"};
+ static const char *const SolarisX86Triples[] = {"i386-pc-solaris2.11"};
+ static const char *const SolarisX86_64Triples[] = {"x86_64-pc-solaris2.11"};
LibDirs.append(begin(SolarisLibDirs), end(SolarisLibDirs));
BiarchLibDirs.append(begin(SolarisLibDirs), end(SolarisLibDirs));
switch (TargetTriple.getArch()) {
@@ -2248,9 +2621,6 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
static const char *const AArch64AndroidTriples[] = {
"aarch64-linux-android"};
static const char *const ARMAndroidTriples[] = {"arm-linux-androideabi"};
- static const char *const MIPSELAndroidTriples[] = {"mipsel-linux-android"};
- static const char *const MIPS64ELAndroidTriples[] = {
- "mips64el-linux-android"};
static const char *const X86AndroidTriples[] = {"i686-linux-android"};
static const char *const X86_64AndroidTriples[] = {"x86_64-linux-android"};
@@ -2265,22 +2635,6 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
LibDirs.append(begin(ARMLibDirs), end(ARMLibDirs));
TripleAliases.append(begin(ARMAndroidTriples), end(ARMAndroidTriples));
break;
- case llvm::Triple::mipsel:
- LibDirs.append(begin(MIPSELLibDirs), end(MIPSELLibDirs));
- TripleAliases.append(begin(MIPSELAndroidTriples),
- end(MIPSELAndroidTriples));
- BiarchLibDirs.append(begin(MIPS64ELLibDirs), end(MIPS64ELLibDirs));
- BiarchTripleAliases.append(begin(MIPS64ELAndroidTriples),
- end(MIPS64ELAndroidTriples));
- break;
- case llvm::Triple::mips64el:
- LibDirs.append(begin(MIPS64ELLibDirs), end(MIPS64ELLibDirs));
- TripleAliases.append(begin(MIPS64ELAndroidTriples),
- end(MIPS64ELAndroidTriples));
- BiarchLibDirs.append(begin(MIPSELLibDirs), end(MIPSELLibDirs));
- BiarchTripleAliases.append(begin(MIPSELAndroidTriples),
- end(MIPSELAndroidTriples));
- break;
case llvm::Triple::x86_64:
LibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));
TripleAliases.append(begin(X86_64AndroidTriples),
@@ -2303,6 +2657,23 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
return;
}
+ if (TargetTriple.isOSHurd()) {
+ switch (TargetTriple.getArch()) {
+ case llvm::Triple::x86_64:
+ LibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));
+ TripleAliases.push_back("x86_64-gnu");
+ break;
+ case llvm::Triple::x86:
+ LibDirs.append(begin(X86LibDirs), end(X86LibDirs));
+ TripleAliases.push_back("i686-gnu");
+ break;
+ default:
+ break;
+ }
+
+ return;
+ }
+
switch (TargetTriple.getArch()) {
case llvm::Triple::aarch64:
LibDirs.append(begin(AArch64LibDirs), end(AArch64LibDirs));
@@ -2319,7 +2690,9 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
case llvm::Triple::arm:
case llvm::Triple::thumb:
LibDirs.append(begin(ARMLibDirs), end(ARMLibDirs));
- if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF) {
+ if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF ||
+ TargetTriple.getEnvironment() == llvm::Triple::MuslEABIHF ||
+ TargetTriple.getEnvironment() == llvm::Triple::EABIHF) {
TripleAliases.append(begin(ARMHFTriples), end(ARMHFTriples));
} else {
TripleAliases.append(begin(ARMTriples), end(ARMTriples));
@@ -2328,7 +2701,9 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
case llvm::Triple::armeb:
case llvm::Triple::thumbeb:
LibDirs.append(begin(ARMebLibDirs), end(ARMebLibDirs));
- if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF) {
+ if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF ||
+ TargetTriple.getEnvironment() == llvm::Triple::MuslEABIHF ||
+ TargetTriple.getEnvironment() == llvm::Triple::EABIHF) {
TripleAliases.append(begin(ARMebHFTriples), end(ARMebHFTriples));
} else {
TripleAliases.append(begin(ARMebTriples), end(ARMebTriples));
@@ -2338,6 +2713,10 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
LibDirs.append(begin(AVRLibDirs), end(AVRLibDirs));
TripleAliases.append(begin(AVRTriples), end(AVRTriples));
break;
+ case llvm::Triple::csky:
+ LibDirs.append(begin(CSKYLibDirs), end(CSKYLibDirs));
+ TripleAliases.append(begin(CSKYTriples), end(CSKYTriples));
+ break;
case llvm::Triple::x86_64:
if (TargetTriple.isX32()) {
LibDirs.append(begin(X32LibDirs), end(X32LibDirs));
@@ -2365,6 +2744,11 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
BiarchTripleAliases.append(begin(X32Triples), end(X32Triples));
}
break;
+ // TODO: Handle loongarch32.
+ case llvm::Triple::loongarch64:
+ LibDirs.append(begin(LoongArch64LibDirs), end(LoongArch64LibDirs));
+ TripleAliases.append(begin(LoongArch64Triples), end(LoongArch64Triples));
+ break;
case llvm::Triple::m68k:
LibDirs.append(begin(M68kLibDirs), end(M68kLibDirs));
TripleAliases.append(begin(M68kTriples), end(M68kTriples));
@@ -2466,10 +2850,6 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
break;
}
- // Always append the drivers target triple to the end, in case it doesn't
- // match any of our aliases.
- TripleAliases.push_back(TargetTriple.str());
-
// Also include the multiarch variant if it's different.
if (TargetTriple.str() != BiarchTriple.str())
BiarchTripleAliases.push_back(BiarchTriple.str());
@@ -2487,6 +2867,8 @@ bool Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs(
if (isArmOrThumbArch(TargetArch) && TargetTriple.isAndroid()) {
// It should also work without multilibs in a simplified toolchain.
findAndroidArmMultilibs(D, TargetTriple, Path, Args, Detected);
+ } else if (TargetTriple.isCSKY()) {
+ findCSKYMultilibs(D, TargetTriple, Path, Args, Detected);
} else if (TargetTriple.isMIPS()) {
if (!findMIPSMultilibs(D, TargetTriple, Path, Args, Detected))
return false;
@@ -2502,7 +2884,9 @@ bool Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs(
}
Multilibs = Detected.Multilibs;
- SelectedMultilib = Detected.SelectedMultilib;
+ SelectedMultilib = Detected.SelectedMultilibs.empty()
+ ? Multilib()
+ : Detected.SelectedMultilibs.back();
BiarchSibling = Detected.BiarchSibling;
return true;
@@ -2577,7 +2961,7 @@ bool Generic_GCC::GCCInstallationDetector::ScanGentooConfigs(
const llvm::Triple &TargetTriple, const ArgList &Args,
const SmallVectorImpl<StringRef> &CandidateTriples,
const SmallVectorImpl<StringRef> &CandidateBiarchTriples) {
- if (!D.getVFS().exists(D.SysRoot + GentooConfigDir))
+ if (!D.getVFS().exists(concat(D.SysRoot, GentooConfigDir)))
return false;
for (StringRef CandidateTriple : CandidateTriples) {
@@ -2596,8 +2980,8 @@ bool Generic_GCC::GCCInstallationDetector::ScanGentooGccConfig(
const llvm::Triple &TargetTriple, const ArgList &Args,
StringRef CandidateTriple, bool NeedsBiarchSuffix) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
- D.getVFS().getBufferForFile(D.SysRoot + GentooConfigDir + "/config-" +
- CandidateTriple.str());
+ D.getVFS().getBufferForFile(concat(D.SysRoot, GentooConfigDir,
+ "/config-" + CandidateTriple.str()));
if (File) {
SmallVector<StringRef, 2> Lines;
File.get()->getBuffer().split(Lines, "\n");
@@ -2608,8 +2992,8 @@ bool Generic_GCC::GCCInstallationDetector::ScanGentooGccConfig(
continue;
// Process the config file pointed to by CURRENT.
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ConfigFile =
- D.getVFS().getBufferForFile(D.SysRoot + GentooConfigDir + "/" +
- Line.str());
+ D.getVFS().getBufferForFile(
+ concat(D.SysRoot, GentooConfigDir, "/" + Line));
std::pair<StringRef, StringRef> ActiveVersion = Line.rsplit('-');
// List of paths to scan for libraries.
SmallVector<StringRef, 4> GentooScanPaths;
@@ -2642,7 +3026,7 @@ bool Generic_GCC::GCCInstallationDetector::ScanGentooGccConfig(
// Scan all paths for GCC libraries.
for (const auto &GentooScanPath : GentooScanPaths) {
- std::string GentooPath = D.SysRoot + std::string(GentooScanPath);
+ std::string GentooPath = concat(D.SysRoot, GentooScanPath);
if (D.getVFS().exists(GentooPath + "/crtbegin.o")) {
if (!ScanGCCForMultilibs(TargetTriple, Args, GentooPath,
NeedsBiarchSuffix))
@@ -2697,21 +3081,26 @@ Tool *Generic_GCC::buildLinker() const { return new tools::gcc::Linker(*this); }
void Generic_GCC::printVerboseInfo(raw_ostream &OS) const {
// Print the information about how we detected the GCC installation.
GCCInstallation.print(OS);
- CudaInstallation.print(OS);
- RocmInstallation.print(OS);
+ CudaInstallation->print(OS);
+ RocmInstallation->print(OS);
}
-bool Generic_GCC::IsUnwindTablesDefault(const ArgList &Args) const {
+ToolChain::UnwindTableLevel
+Generic_GCC::getDefaultUnwindTableLevel(const ArgList &Args) const {
switch (getArch()) {
case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_be:
case llvm::Triple::ppc:
case llvm::Triple::ppcle:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ case llvm::Triple::x86:
case llvm::Triple::x86_64:
- return true;
+ return UnwindTableLevel::Asynchronous;
default:
- return false;
+ return UnwindTableLevel::None;
}
}
@@ -2727,7 +3116,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();
@@ -2735,40 +3126,12 @@ bool Generic_GCC::isPICDefaultForced() const {
bool Generic_GCC::IsIntegratedAssemblerDefault() const {
switch (getTriple().getArch()) {
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- case llvm::Triple::aarch64:
- case llvm::Triple::aarch64_be:
- case llvm::Triple::arm:
- case llvm::Triple::armeb:
- case llvm::Triple::avr:
- case llvm::Triple::bpfel:
- case llvm::Triple::bpfeb:
- case llvm::Triple::thumb:
- case llvm::Triple::thumbeb:
- case llvm::Triple::ppc:
- case llvm::Triple::ppcle:
- case llvm::Triple::ppc64:
- case llvm::Triple::ppc64le:
- case llvm::Triple::riscv32:
- case llvm::Triple::riscv64:
- case llvm::Triple::systemz:
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- case llvm::Triple::msp430:
- case llvm::Triple::m68k:
- return true;
- case llvm::Triple::sparc:
- case llvm::Triple::sparcel:
- case llvm::Triple::sparcv9:
- if (getTriple().isOSFreeBSD() || getTriple().isOSOpenBSD() ||
- getTriple().isOSSolaris())
- return true;
+ case llvm::Triple::nvptx:
+ case llvm::Triple::nvptx64:
+ case llvm::Triple::xcore:
return false;
default:
- return false;
+ return true;
}
}
@@ -2794,6 +3157,7 @@ void Generic_GCC::AddMultilibPaths(const Driver &D,
path_list &Paths) {
// Add the multilib suffixed paths where they are available.
if (GCCInstallation.isValid()) {
+ assert(!SelectedMultilibs.empty());
const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
const std::string &LibPath =
std::string(GCCInstallation.getParentLibPath());
@@ -2801,13 +3165,19 @@ void Generic_GCC::AddMultilibPaths(const Driver &D,
// Sourcery CodeBench MIPS toolchain holds some libraries under
// a biarch-like suffix of the GCC installation.
if (const auto &PathsCallback = Multilibs.filePathsCallback())
- for (const auto &Path : PathsCallback(SelectedMultilib))
+ for (const auto &Path : PathsCallback(SelectedMultilibs.back()))
addPathIfExists(D, GCCInstallation.getInstallPath() + Path, Paths);
// Add lib/gcc/$triple/$version, with an optional /multilib suffix.
- addPathIfExists(
- D, GCCInstallation.getInstallPath() + SelectedMultilib.gccSuffix(),
- Paths);
+ addPathIfExists(D,
+ GCCInstallation.getInstallPath() +
+ SelectedMultilibs.back().gccSuffix(),
+ Paths);
+
+ // Add lib/gcc/$triple/$libdir
+ // For GCC built with --enable-version-specific-runtime-libs.
+ addPathIfExists(D, GCCInstallation.getInstallPath() + "/../" + OSLibDir,
+ Paths);
// GCC cross compiling toolchains will install target libraries which ship
// as part of the toolchain under <prefix>/<triple>/<libdir> rather than as
@@ -2829,7 +3199,7 @@ void Generic_GCC::AddMultilibPaths(const Driver &D,
// Clang diverges from GCC's behavior.
addPathIfExists(D,
LibPath + "/../" + GCCTriple.str() + "/lib/../" + OSLibDir +
- SelectedMultilib.osSuffix(),
+ SelectedMultilibs.back().osSuffix(),
Paths);
// If the GCC installation we found is inside of the sysroot, we want to
@@ -2841,7 +3211,7 @@ void Generic_GCC::AddMultilibPaths(const Driver &D,
// the cross. Note that GCC does include some of these directories in some
// configurations but this seems somewhere between questionable and simply
// a bug.
- if (StringRef(LibPath).startswith(SysRoot))
+ if (StringRef(LibPath).starts_with(SysRoot))
addPathIfExists(D, LibPath + "/../" + OSLibDir, Paths);
}
}
@@ -2902,34 +3272,53 @@ Generic_GCC::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
const Driver &D = getDriver();
std::string SysRoot = computeSysRoot();
- std::string Target = getTripleString();
+ if (SysRoot.empty())
+ SysRoot = llvm::sys::path::get_separator();
- auto AddIncludePath = [&](std::string Path) {
+ auto AddIncludePath = [&](StringRef Path, bool TargetDirRequired = false) {
std::string Version = detectLibcxxVersion(Path);
if (Version.empty())
return false;
// First add the per-target include path if it exists.
- std::string TargetDir = Path + "/" + Target + "/c++/" + Version;
- if (D.getVFS().exists(TargetDir))
- addSystemInclude(DriverArgs, CC1Args, TargetDir);
+ bool TargetDirExists = false;
+ std::optional<std::string> TargetIncludeDir = getTargetSubDirPath(Path);
+ if (TargetIncludeDir) {
+ SmallString<128> TargetDir(*TargetIncludeDir);
+ llvm::sys::path::append(TargetDir, "c++", Version);
+ if (D.getVFS().exists(TargetDir)) {
+ addSystemInclude(DriverArgs, CC1Args, TargetDir);
+ TargetDirExists = true;
+ }
+ }
+ if (TargetDirRequired && !TargetDirExists)
+ return false;
// Second add the generic one.
- addSystemInclude(DriverArgs, CC1Args, Path + "/c++/" + Version);
+ SmallString<128> GenericDir(Path);
+ llvm::sys::path::append(GenericDir, "c++", Version);
+ addSystemInclude(DriverArgs, CC1Args, GenericDir);
return true;
};
- // Android never uses the libc++ headers installed alongside the toolchain,
- // which are generally incompatible with the NDK libraries anyway.
- if (!getTriple().isAndroid())
- if (AddIncludePath(getDriver().Dir + "/../include"))
- return;
+ // Android only uses the libc++ headers installed alongside the toolchain if
+ // they contain an Android-specific target include path, otherwise they're
+ // incompatible with the NDK libraries.
+ SmallString<128> DriverIncludeDir(getDriver().Dir);
+ llvm::sys::path::append(DriverIncludeDir, "..", "include");
+ if (AddIncludePath(DriverIncludeDir,
+ /*TargetDirRequired=*/getTriple().isAndroid()))
+ return;
// If this is a development, non-installed, clang, libcxx will
// not be found at ../include/c++ but it likely to be found at
// one of the following two locations:
- if (AddIncludePath(SysRoot + "/usr/local/include"))
+ SmallString<128> UsrLocalIncludeDir(SysRoot);
+ llvm::sys::path::append(UsrLocalIncludeDir, "usr", "local", "include");
+ if (AddIncludePath(UsrLocalIncludeDir))
return;
- if (AddIncludePath(SysRoot + "/usr/include"))
+ SmallString<128> UsrIncludeDir(SysRoot);
+ llvm::sys::path::append(UsrIncludeDir, "usr", "include");
+ if (AddIncludePath(UsrIncludeDir))
return;
}
@@ -2987,6 +3376,15 @@ bool Generic_GCC::addGCCLibStdCxxIncludePaths(
TripleStr, Multilib.includeSuffix(), DriverArgs, CC1Args))
return true;
+ // Try /gcc/$triple/$version/include/c++/ (gcc --print-multiarch is not
+ // empty). Like above but for GCC built with
+ // --enable-version-specific-runtime-libs.
+ if (addLibStdCXXIncludePaths(LibDir.str() + "/gcc/" + TripleStr + "/" +
+ Version.Text + "/include/c++/",
+ TripleStr, Multilib.includeSuffix(), DriverArgs,
+ CC1Args))
+ return true;
+
// Detect Debian g++-multiarch-incdir.diff.
if (addLibStdCXXIncludePaths(LibDir.str() + "/../include/c++/" + Version.Text,
DebianMultiarch, Multilib.includeSuffix(),
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.h
index 40fd756a5653..0b664a182d75 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Gnu.h
@@ -10,6 +10,7 @@
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_GNU_H
#include "Cuda.h"
+#include "LazyDetector.h"
#include "ROCm.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
@@ -22,12 +23,12 @@ struct DetectedMultilibs {
/// The set of multilibs that the detected installation supports.
MultilibSet Multilibs;
- /// The primary multilib appropriate for the given flags.
- Multilib SelectedMultilib;
+ /// The multilibs appropriate for the given flags.
+ llvm::SmallVector<Multilib> SelectedMultilibs;
/// On Biarch systems, this corresponds to the default multilib when
/// targeting the non-default multilib. Otherwise, it is empty.
- llvm::Optional<Multilib> BiarchSibling;
+ std::optional<Multilib> BiarchSibling;
};
bool findMIPSMultilibs(const Driver &D, const llvm::Triple &TargetTriple,
@@ -201,7 +202,7 @@ public:
Multilib SelectedMultilib;
/// On Biarch systems, this corresponds to the default multilib when
/// targeting the non-default multilib. Otherwise, it is empty.
- llvm::Optional<Multilib> BiarchSibling;
+ std::optional<Multilib> BiarchSibling;
GCCVersion Version;
@@ -217,8 +218,7 @@ public:
public:
explicit GCCInstallationDetector(const Driver &D) : IsValid(false), D(D) {}
- void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args,
- ArrayRef<std::string> ExtraTripleAliases = None);
+ void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args);
/// Check whether we detected a valid GCC install.
bool isValid() const { return IsValid; }
@@ -286,8 +286,8 @@ public:
protected:
GCCInstallationDetector GCCInstallation;
- CudaInstallationDetector CudaInstallation;
- RocmInstallationDetector RocmInstallation;
+ LazyDetector<CudaInstallationDetector> CudaInstallation;
+ LazyDetector<RocmInstallationDetector> RocmInstallation;
public:
Generic_GCC(const Driver &D, const llvm::Triple &Triple,
@@ -296,9 +296,10 @@ public:
void printVerboseInfo(raw_ostream &OS) const override;
- bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override;
+ UnwindTableLevel
+ getDefaultUnwindTableLevel(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/contrib/llvm-project/clang/lib/Driver/ToolChains/HIP.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/HIP.cpp
deleted file mode 100644
index c4e840de86e1..000000000000
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/HIP.cpp
+++ /dev/null
@@ -1,458 +0,0 @@
-//===--- HIP.cpp - HIP Tool and ToolChain Implementations -------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "HIP.h"
-#include "AMDGPU.h"
-#include "CommonArgs.h"
-#include "clang/Basic/Cuda.h"
-#include "clang/Basic/TargetID.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/Support/Alignment.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/TargetParser.h"
-
-using namespace clang::driver;
-using namespace clang::driver::toolchains;
-using namespace clang::driver::tools;
-using namespace clang;
-using namespace llvm::opt;
-
-#if defined(_WIN32) || defined(_WIN64)
-#define NULL_FILE "nul"
-#else
-#define NULL_FILE "/dev/null"
-#endif
-
-namespace {
-const unsigned HIPCodeObjectAlign = 4096;
-} // namespace
-
-void AMDGCN::Linker::constructLldCommand(Compilation &C, const JobAction &JA,
- const InputInfoList &Inputs,
- const InputInfo &Output,
- const llvm::opt::ArgList &Args) const {
- // Construct lld command.
- // The output from ld.lld is an HSA code object file.
- ArgStringList LldArgs{"-flavor", "gnu", "--no-undefined", "-shared",
- "-plugin-opt=-amdgpu-internalize-symbols"};
-
- auto &TC = getToolChain();
- auto &D = TC.getDriver();
- assert(!Inputs.empty() && "Must have at least one input.");
- bool IsThinLTO = D.getLTOMode(/*IsOffload=*/true) == LTOK_Thin;
- addLTOOptions(TC, Args, LldArgs, Output, Inputs[0], IsThinLTO);
-
- // Extract all the -m options
- std::vector<llvm::StringRef> Features;
- amdgpu::getAMDGPUTargetFeatures(D, TC.getTriple(), Args, Features);
-
- // Add features to mattr such as cumode
- std::string MAttrString = "-plugin-opt=-mattr=";
- for (auto OneFeature : unifyTargetFeatures(Features)) {
- MAttrString.append(Args.MakeArgString(OneFeature));
- if (OneFeature != Features.back())
- MAttrString.append(",");
- }
- if (!Features.empty())
- LldArgs.push_back(Args.MakeArgString(MAttrString));
-
- // ToDo: Remove this option after AMDGPU backend supports ISA-level linking.
- // Since AMDGPU backend currently does not support ISA-level linking, all
- // called functions need to be imported.
- if (IsThinLTO)
- LldArgs.push_back(Args.MakeArgString("-plugin-opt=-force-import-all"));
-
- for (const Arg *A : Args.filtered(options::OPT_mllvm)) {
- LldArgs.push_back(
- Args.MakeArgString(Twine("-plugin-opt=") + A->getValue(0)));
- }
-
- if (C.getDriver().isSaveTempsEnabled())
- LldArgs.push_back("-save-temps");
-
- addLinkerCompressDebugSectionsOption(TC, Args, LldArgs);
-
- LldArgs.append({"-o", Output.getFilename()});
- 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));
-}
-
-// Construct a clang-offload-bundler command to bundle code objects for
-// different GPU's into a HIP fat binary.
-void AMDGCN::constructHIPFatbinCommand(Compilation &C, const JobAction &JA,
- StringRef OutputFileName, const InputInfoList &Inputs,
- const llvm::opt::ArgList &Args, const Tool& T) {
- // Construct clang-offload-bundler command to bundle object files for
- // for different GPU archs.
- ArgStringList BundlerArgs;
- BundlerArgs.push_back(Args.MakeArgString("-type=o"));
- BundlerArgs.push_back(
- Args.MakeArgString("-bundle-align=" + Twine(HIPCodeObjectAlign)));
-
- // ToDo: Remove the dummy host binary entry which is required by
- // clang-offload-bundler.
- std::string BundlerTargetArg = "-targets=host-x86_64-unknown-linux";
- std::string BundlerInputArg = "-inputs=" NULL_FILE;
-
- // For code object version 2 and 3, the offload kind in bundle ID is 'hip'
- // for backward compatibility. For code object version 4 and greater, the
- // offload kind in bundle ID is 'hipv4'.
- std::string OffloadKind = "hip";
- if (getAMDGPUCodeObjectVersion(C.getDriver(), Args) >= 4)
- OffloadKind = OffloadKind + "v4";
- for (const auto &II : Inputs) {
- const auto* A = II.getAction();
- BundlerTargetArg = BundlerTargetArg + "," + OffloadKind +
- "-amdgcn-amd-amdhsa--" +
- StringRef(A->getOffloadingArch()).str();
- BundlerInputArg = BundlerInputArg + "," + II.getFilename();
- }
- BundlerArgs.push_back(Args.MakeArgString(BundlerTargetArg));
- BundlerArgs.push_back(Args.MakeArgString(BundlerInputArg));
-
- std::string Output = std::string(OutputFileName);
- auto BundlerOutputArg =
- Args.MakeArgString(std::string("-outputs=").append(Output));
- BundlerArgs.push_back(BundlerOutputArg);
-
- const char *Bundler = Args.MakeArgString(
- T.getToolChain().GetProgramPath("clang-offload-bundler"));
- C.addCommand(std::make_unique<Command>(
- JA, T, ResponseFileSupport::None(), Bundler, BundlerArgs, Inputs,
- InputInfo(&JA, Args.MakeArgString(Output))));
-}
-
-/// Add Generated HIP Object File which has device images embedded into the
-/// host to the argument list for linking. Using MC directives, embed the
-/// device code and also define symbols required by the code generation so that
-/// the image can be retrieved at runtime.
-void AMDGCN::Linker::constructGenerateObjFileFromHIPFatBinary(
- Compilation &C, const InputInfo &Output,
- const InputInfoList &Inputs, const ArgList &Args,
- const JobAction &JA) const {
- const ToolChain &TC = getToolChain();
- std::string Name =
- std::string(llvm::sys::path::stem(Output.getFilename()));
-
- // Create Temp Object File Generator,
- // Offload Bundled file and Bundled Object file.
- // Keep them if save-temps is enabled.
- const char *McinFile;
- const char *BundleFile;
- if (C.getDriver().isSaveTempsEnabled()) {
- McinFile = C.getArgs().MakeArgString(Name + ".mcin");
- BundleFile = C.getArgs().MakeArgString(Name + ".hipfb");
- } else {
- auto TmpNameMcin = C.getDriver().GetTemporaryPath(Name, "mcin");
- McinFile = C.addTempFile(C.getArgs().MakeArgString(TmpNameMcin));
- auto TmpNameFb = C.getDriver().GetTemporaryPath(Name, "hipfb");
- BundleFile = C.addTempFile(C.getArgs().MakeArgString(TmpNameFb));
- }
- constructHIPFatbinCommand(C, JA, BundleFile, Inputs, Args, *this);
-
- // Create a buffer to write the contents of the temp obj generator.
- std::string ObjBuffer;
- llvm::raw_string_ostream ObjStream(ObjBuffer);
-
- // Add MC directives to embed target binaries. We ensure that each
- // section and image is 16-byte aligned. This is not mandatory, but
- // increases the likelihood of data to be aligned with a cache block
- // in several main host machines.
- ObjStream << "# HIP Object Generator\n";
- ObjStream << "# *** Automatically generated by Clang ***\n";
- ObjStream << " .protected __hip_fatbin\n";
- ObjStream << " .type __hip_fatbin,@object\n";
- ObjStream << " .section .hip_fatbin,\"a\",@progbits\n";
- ObjStream << " .globl __hip_fatbin\n";
- ObjStream << " .p2align " << llvm::Log2(llvm::Align(HIPCodeObjectAlign))
- << "\n";
- ObjStream << "__hip_fatbin:\n";
- ObjStream << " .incbin \"" << BundleFile << "\"\n";
- ObjStream.flush();
-
- // Dump the contents of the temp object file gen if the user requested that.
- // We support this option to enable testing of behavior with -###.
- if (C.getArgs().hasArg(options::OPT_fhip_dump_offload_linker_script))
- llvm::errs() << ObjBuffer;
-
- // Open script file and write the contents.
- std::error_code EC;
- llvm::raw_fd_ostream Objf(McinFile, EC, llvm::sys::fs::OF_None);
-
- if (EC) {
- C.getDriver().Diag(clang::diag::err_unable_to_make_temp) << EC.message();
- return;
- }
-
- Objf << ObjBuffer;
-
- ArgStringList McArgs{"-o", Output.getFilename(),
- McinFile, "--filetype=obj"};
- const char *Mc = Args.MakeArgString(TC.GetProgramPath("llvm-mc"));
- C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
- Mc, McArgs, Inputs, Output));
-}
-
-// For amdgcn the inputs of the linker job are device bitcode and output is
-// object file. It calls llvm-link, opt, llc, then lld steps.
-void AMDGCN::Linker::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
- if (Inputs.size() > 0 &&
- Inputs[0].getType() == types::TY_Image &&
- JA.getType() == types::TY_Object)
- return constructGenerateObjFileFromHIPFatBinary(C, Output, Inputs, Args, JA);
-
- if (JA.getType() == types::TY_HIP_FATBIN)
- return constructHIPFatbinCommand(C, JA, Output.getFilename(), Inputs, Args, *this);
-
- return constructLldCommand(C, JA, Inputs, Output, Args);
-}
-
-HIPToolChain::HIPToolChain(const Driver &D, const llvm::Triple &Triple,
- const ToolChain &HostTC, const ArgList &Args)
- : ROCMToolChain(D, Triple, Args), HostTC(HostTC) {
- // Lookup binaries into the driver directory, this is used to
- // discover the clang-offload-bundler executable.
- getProgramPaths().push_back(getDriver().Dir);
-}
-
-void HIPToolChain::addClangTargetOptions(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args,
- Action::OffloadKind DeviceOffloadingKind) const {
- HostTC.addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadingKind);
-
- assert(DeviceOffloadingKind == Action::OFK_HIP &&
- "Only HIP offloading kinds are supported for GPUs.");
-
- CC1Args.push_back("-fcuda-is-device");
-
- if (DriverArgs.hasFlag(options::OPT_fcuda_approx_transcendentals,
- options::OPT_fno_cuda_approx_transcendentals, false))
- CC1Args.push_back("-fcuda-approx-transcendentals");
-
- if (!DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
- false))
- CC1Args.append({"-mllvm", "-amdgpu-internalize-symbols"});
-
- StringRef MaxThreadsPerBlock =
- DriverArgs.getLastArgValue(options::OPT_gpu_max_threads_per_block_EQ);
- if (!MaxThreadsPerBlock.empty()) {
- std::string ArgStr =
- std::string("--gpu-max-threads-per-block=") + MaxThreadsPerBlock.str();
- CC1Args.push_back(DriverArgs.MakeArgStringRef(ArgStr));
- }
-
- CC1Args.push_back("-fcuda-allow-variadic-functions");
-
- // Default to "hidden" visibility, as object level linking will not be
- // supported for the foreseeable future.
- if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
- options::OPT_fvisibility_ms_compat)) {
- CC1Args.append({"-fvisibility", "hidden"});
- 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::opt::DerivedArgList *
-HIPToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
- StringRef BoundArch,
- Action::OffloadKind DeviceOffloadKind) const {
- DerivedArgList *DAL =
- HostTC.TranslateArgs(Args, BoundArch, DeviceOffloadKind);
- if (!DAL)
- DAL = new DerivedArgList(Args.getBaseArgs());
-
- const OptTable &Opts = getDriver().getOpts();
-
- for (Arg *A : Args) {
- if (!shouldSkipArgument(A))
- DAL->append(A);
- }
-
- if (!BoundArch.empty()) {
- DAL->eraseArg(options::OPT_mcpu_EQ);
- DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_mcpu_EQ), BoundArch);
- checkTargetID(*DAL);
- }
-
- return DAL;
-}
-
-Tool *HIPToolChain::buildLinker() const {
- assert(getTriple().getArch() == llvm::Triple::amdgcn);
- return new tools::AMDGCN::Linker(*this);
-}
-
-void HIPToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {
- HostTC.addClangWarningOptions(CC1Args);
-}
-
-ToolChain::CXXStdlibType
-HIPToolChain::GetCXXStdlibType(const ArgList &Args) const {
- return HostTC.GetCXXStdlibType(Args);
-}
-
-void HIPToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const {
- HostTC.AddClangSystemIncludeArgs(DriverArgs, CC1Args);
-}
-
-void HIPToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &Args,
- ArgStringList &CC1Args) const {
- HostTC.AddClangCXXStdlibIncludeArgs(Args, CC1Args);
-}
-
-void HIPToolChain::AddIAMCUIncludeArgs(const ArgList &Args,
- ArgStringList &CC1Args) const {
- HostTC.AddIAMCUIncludeArgs(Args, CC1Args);
-}
-
-void HIPToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const {
- RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
-}
-
-SanitizerMask HIPToolChain::getSupportedSanitizers() const {
- // The HIPToolChain only supports sanitizers in the sense that it allows
- // sanitizer arguments on the command line if they are supported by the host
- // toolchain. The HIPToolChain will actually ignore any command line
- // arguments for any of these "supported" sanitizers. That means that no
- // sanitization of device code is actually supported at this time.
- //
- // This behavior is necessary because the host and device toolchains
- // invocations often share the command line, so the device toolchain must
- // tolerate flags meant only for the host toolchain.
- return HostTC.getSupportedSanitizers();
-}
-
-VersionTuple HIPToolChain::computeMSVCVersion(const Driver *D,
- const ArgList &Args) const {
- return HostTC.computeMSVCVersion(D, Args);
-}
-
-llvm::SmallVector<std::string, 12>
-HIPToolChain::getHIPDeviceLibs(const llvm::opt::ArgList &DriverArgs) const {
- llvm::SmallVector<std::string, 12> BCLibs;
- if (DriverArgs.hasArg(options::OPT_nogpulib))
- return {};
- ArgStringList LibraryPaths;
-
- // Find in --hip-device-lib-path and HIP_LIBRARY_PATH.
- for (auto Path : RocmInstallation.getRocmDeviceLibPathArg())
- LibraryPaths.push_back(DriverArgs.MakeArgString(Path));
-
- addDirectoryList(DriverArgs, LibraryPaths, "", "HIP_DEVICE_LIB_PATH");
-
- // Maintain compatability with --hip-device-lib.
- auto BCLibArgs = DriverArgs.getAllArgValues(options::OPT_hip_device_lib_EQ);
- if (!BCLibArgs.empty()) {
- llvm::for_each(BCLibArgs, [&](StringRef BCName) {
- StringRef FullName;
- for (std::string LibraryPath : LibraryPaths) {
- SmallString<128> Path(LibraryPath);
- llvm::sys::path::append(Path, BCName);
- FullName = Path;
- if (llvm::sys::fs::exists(FullName)) {
- BCLibs.push_back(FullName.str());
- return;
- }
- }
- getDriver().Diag(diag::err_drv_no_such_file) << BCName;
- });
- } else {
- if (!RocmInstallation.hasDeviceLibrary()) {
- getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 0;
- return {};
- }
- StringRef GpuArch = getGPUArch(DriverArgs);
- assert(!GpuArch.empty() && "Must have an explicit GPU arch.");
-
- // If --hip-device-lib is not set, add the default bitcode libraries.
- if (DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
- options::OPT_fno_gpu_sanitize, false)) {
- auto AsanRTL = RocmInstallation.getAsanRTLPath();
- if (AsanRTL.empty()) {
- unsigned DiagID = getDriver().getDiags().getCustomDiagID(
- DiagnosticsEngine::Error,
- "AMDGPU address sanitizer runtime library (asanrtl) is not found. "
- "Please install ROCm device library which supports address "
- "sanitizer");
- getDriver().Diag(DiagID);
- return {};
- } else
- BCLibs.push_back(AsanRTL.str());
- }
-
- // Add the HIP specific bitcode library.
- BCLibs.push_back(RocmInstallation.getHIPPath().str());
-
- // Add common device libraries like ocml etc.
- BCLibs.append(getCommonDeviceLibNames(DriverArgs, GpuArch.str()));
-
- // Add instrument lib.
- auto InstLib =
- DriverArgs.getLastArgValue(options::OPT_gpu_instrument_lib_EQ);
- if (InstLib.empty())
- return BCLibs;
- if (llvm::sys::fs::exists(InstLib))
- BCLibs.push_back(InstLib.str());
- else
- getDriver().Diag(diag::err_drv_no_such_file) << InstLib;
- }
-
- return BCLibs;
-}
-
-void HIPToolChain::checkTargetID(const llvm::opt::ArgList &DriverArgs) const {
- auto PTID = getParsedTargetID(DriverArgs);
- 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();
- }
- }
-}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/HIPAMD.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/HIPAMD.cpp
new file mode 100644
index 000000000000..ccb36a6c846c
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/HIPAMD.cpp
@@ -0,0 +1,434 @@
+//===--- HIPAMD.cpp - HIP Tool and ToolChain Implementations ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "HIPAMD.h"
+#include "AMDGPU.h"
+#include "CommonArgs.h"
+#include "HIPUtility.h"
+#include "clang/Basic/Cuda.h"
+#include "clang/Basic/TargetID.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 "clang/Driver/SanitizerArgs.h"
+#include "llvm/Support/Alignment.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/TargetParser/TargetParser.h"
+
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+#if defined(_WIN32) || defined(_WIN64)
+#define NULL_FILE "nul"
+#else
+#define NULL_FILE "/dev/null"
+#endif
+
+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, true))
+ 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::constructLlvmLinkCommand(Compilation &C,
+ const JobAction &JA,
+ const InputInfoList &Inputs,
+ const InputInfo &Output,
+ const llvm::opt::ArgList &Args) const {
+ // Construct llvm-link command.
+ // The output from llvm-link is a bitcode file.
+ ArgStringList LlvmLinkArgs;
+
+ assert(!Inputs.empty() && "Must have at least one input.");
+
+ LlvmLinkArgs.append({"-o", Output.getFilename()});
+ for (auto Input : Inputs)
+ LlvmLinkArgs.push_back(Input.getFilename());
+
+ // Look for archive of bundled bitcode in arguments, and add temporary files
+ // for the extracted archive of bitcode to inputs.
+ auto TargetID = Args.getLastArgValue(options::OPT_mcpu_EQ);
+ AddStaticDeviceLibsLinking(C, *this, JA, Inputs, Args, LlvmLinkArgs, "amdgcn",
+ TargetID, /*IsBitCodeSDL=*/true);
+
+ const char *LlvmLink =
+ Args.MakeArgString(getToolChain().GetProgramPath("llvm-link"));
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ LlvmLink, LlvmLinkArgs, Inputs,
+ Output));
+}
+
+void AMDGCN::Linker::constructLldCommand(Compilation &C, const JobAction &JA,
+ const InputInfoList &Inputs,
+ const InputInfo &Output,
+ const llvm::opt::ArgList &Args) const {
+ // Construct lld command.
+ // The output from ld.lld is an HSA code object file.
+ ArgStringList LldArgs{"-flavor",
+ "gnu",
+ "-m",
+ "elf64_amdgpu",
+ "--no-undefined",
+ "-shared",
+ "-plugin-opt=-amdgpu-internalize-symbols"};
+ if (Args.hasArg(options::OPT_hipstdpar))
+ LldArgs.push_back("-plugin-opt=-amdgpu-enable-hipstdpar");
+
+ auto &TC = getToolChain();
+ auto &D = TC.getDriver();
+ assert(!Inputs.empty() && "Must have at least one input.");
+ bool IsThinLTO = D.getLTOMode(/*IsOffload=*/true) == LTOK_Thin;
+ addLTOOptions(TC, Args, LldArgs, Output, Inputs[0], IsThinLTO);
+
+ // Extract all the -m options
+ std::vector<llvm::StringRef> Features;
+ amdgpu::getAMDGPUTargetFeatures(D, TC.getTriple(), Args, Features);
+
+ // Add features to mattr such as cumode
+ std::string MAttrString = "-plugin-opt=-mattr=";
+ for (auto OneFeature : unifyTargetFeatures(Features)) {
+ MAttrString.append(Args.MakeArgString(OneFeature));
+ if (OneFeature != Features.back())
+ MAttrString.append(",");
+ }
+ if (!Features.empty())
+ LldArgs.push_back(Args.MakeArgString(MAttrString));
+
+ // ToDo: Remove this option after AMDGPU backend supports ISA-level linking.
+ // Since AMDGPU backend currently does not support ISA-level linking, all
+ // called functions need to be imported.
+ if (IsThinLTO)
+ LldArgs.push_back(Args.MakeArgString("-plugin-opt=-force-import-all"));
+
+ if (C.getDriver().isSaveTempsEnabled())
+ LldArgs.push_back("-save-temps");
+
+ addLinkerCompressDebugSectionsOption(TC, Args, LldArgs);
+
+ // Given that host and device linking happen in separate processes, the device
+ // linker doesn't always have the visibility as to which device symbols are
+ // needed by a program, especially for the device symbol dependencies that are
+ // introduced through the host symbol resolution.
+ // For example: host_A() (A.obj) --> host_B(B.obj) --> device_kernel_B()
+ // (B.obj) In this case, the device linker doesn't know that A.obj actually
+ // depends on the kernel functions in B.obj. When linking to static device
+ // library, the device linker may drop some of the device global symbols if
+ // they aren't referenced. As a workaround, we are adding to the
+ // --whole-archive flag such that all global symbols would be linked in.
+ LldArgs.push_back("--whole-archive");
+
+ for (auto *Arg : Args.filtered(options::OPT_Xoffload_linker)) {
+ StringRef ArgVal = Arg->getValue(1);
+ auto SplitArg = ArgVal.split("-mllvm=");
+ if (!SplitArg.second.empty()) {
+ LldArgs.push_back(
+ Args.MakeArgString(Twine("-plugin-opt=") + SplitArg.second));
+ } else {
+ LldArgs.push_back(Args.MakeArgString(ArgVal));
+ }
+ Arg->claim();
+ }
+
+ LldArgs.append({"-o", Output.getFilename()});
+ for (auto Input : Inputs)
+ LldArgs.push_back(Input.getFilename());
+
+ // Look for archive of bundled bitcode in arguments, and add temporary files
+ // for the extracted archive of bitcode to inputs.
+ auto TargetID = Args.getLastArgValue(options::OPT_mcpu_EQ);
+ AddStaticDeviceLibsLinking(C, *this, JA, Inputs, Args, LldArgs, "amdgcn",
+ TargetID, /*IsBitCodeSDL=*/true);
+
+ LldArgs.push_back("--no-whole-archive");
+
+ const char *Lld = Args.MakeArgString(getToolChain().GetProgramPath("lld"));
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Lld, LldArgs, Inputs, Output));
+}
+
+// For amdgcn the inputs of the linker job are device bitcode and output is
+// either an object file or bitcode (-emit-llvm). It calls llvm-link, opt,
+// llc, then lld steps.
+void AMDGCN::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ if (Inputs.size() > 0 &&
+ Inputs[0].getType() == types::TY_Image &&
+ JA.getType() == types::TY_Object)
+ return HIP::constructGenerateObjFileFromHIPFatBinary(C, Output, Inputs,
+ Args, JA, *this);
+
+ if (JA.getType() == types::TY_HIP_FATBIN)
+ return HIP::constructHIPFatbinCommand(C, JA, Output.getFilename(), Inputs,
+ Args, *this);
+
+ if (JA.getType() == types::TY_LLVM_BC)
+ return constructLlvmLinkCommand(C, JA, Inputs, Output, Args);
+
+ return constructLldCommand(C, JA, Inputs, Output, Args);
+}
+
+HIPAMDToolChain::HIPAMDToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ToolChain &HostTC, const ArgList &Args)
+ : ROCMToolChain(D, Triple, Args), HostTC(HostTC) {
+ // 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.
+ if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
+ true))
+ return;
+ for (auto *A : Args.filtered(options::OPT_fsanitize_EQ)) {
+ SanitizerMask K = parseSanitizerValue(A->getValue(), /*AllowGroups=*/false);
+ if (K != SanitizerKind::Address)
+ D.getDiags().Report(clang::diag::warn_drv_unsupported_option_for_target)
+ << A->getAsString(Args) << getTriple().str();
+ }
+}
+
+void HIPAMDToolChain::addClangTargetOptions(
+ const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadingKind) const {
+ HostTC.addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadingKind);
+
+ assert(DeviceOffloadingKind == Action::OFK_HIP &&
+ "Only HIP offloading kinds are supported for GPUs.");
+
+ CC1Args.push_back("-fcuda-is-device");
+
+ if (!DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
+ false))
+ CC1Args.append({"-mllvm", "-amdgpu-internalize-symbols"});
+ if (DriverArgs.hasArgNoClaim(options::OPT_hipstdpar))
+ CC1Args.append({"-mllvm", "-amdgpu-enable-hipstdpar"});
+
+ StringRef MaxThreadsPerBlock =
+ DriverArgs.getLastArgValue(options::OPT_gpu_max_threads_per_block_EQ);
+ if (!MaxThreadsPerBlock.empty()) {
+ std::string ArgStr =
+ (Twine("--gpu-max-threads-per-block=") + MaxThreadsPerBlock).str();
+ CC1Args.push_back(DriverArgs.MakeArgStringRef(ArgStr));
+ }
+
+ CC1Args.push_back("-fcuda-allow-variadic-functions");
+
+ // Default to "hidden" visibility, as object level linking will not be
+ // supported for the foreseeable future.
+ if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
+ options::OPT_fvisibility_ms_compat)) {
+ CC1Args.append({"-fvisibility=hidden"});
+ CC1Args.push_back("-fapply-global-visibility-to-externs");
+ }
+
+ for (auto BCFile : getDeviceLibs(DriverArgs)) {
+ CC1Args.push_back(BCFile.ShouldInternalize ? "-mlink-builtin-bitcode"
+ : "-mlink-bitcode-file");
+ CC1Args.push_back(DriverArgs.MakeArgString(BCFile.Path));
+ }
+}
+
+llvm::opt::DerivedArgList *
+HIPAMDToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
+ StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind) const {
+ DerivedArgList *DAL =
+ HostTC.TranslateArgs(Args, BoundArch, DeviceOffloadKind);
+ if (!DAL)
+ DAL = new DerivedArgList(Args.getBaseArgs());
+
+ const OptTable &Opts = getDriver().getOpts();
+
+ for (Arg *A : Args) {
+ if (!shouldSkipSanitizeOption(*this, Args, BoundArch, A))
+ DAL->append(A);
+ }
+
+ if (!BoundArch.empty()) {
+ DAL->eraseArg(options::OPT_mcpu_EQ);
+ DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_mcpu_EQ), BoundArch);
+ checkTargetID(*DAL);
+ }
+
+ return DAL;
+}
+
+Tool *HIPAMDToolChain::buildLinker() const {
+ assert(getTriple().getArch() == llvm::Triple::amdgcn);
+ return new tools::AMDGCN::Linker(*this);
+}
+
+void HIPAMDToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {
+ HostTC.addClangWarningOptions(CC1Args);
+}
+
+ToolChain::CXXStdlibType
+HIPAMDToolChain::GetCXXStdlibType(const ArgList &Args) const {
+ return HostTC.GetCXXStdlibType(Args);
+}
+
+void HIPAMDToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ HostTC.AddClangSystemIncludeArgs(DriverArgs, CC1Args);
+}
+
+void HIPAMDToolChain::AddClangCXXStdlibIncludeArgs(
+ const ArgList &Args, ArgStringList &CC1Args) const {
+ HostTC.AddClangCXXStdlibIncludeArgs(Args, CC1Args);
+}
+
+void HIPAMDToolChain::AddIAMCUIncludeArgs(const ArgList &Args,
+ ArgStringList &CC1Args) const {
+ HostTC.AddIAMCUIncludeArgs(Args, CC1Args);
+}
+
+void HIPAMDToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args);
+}
+
+SanitizerMask HIPAMDToolChain::getSupportedSanitizers() const {
+ // The HIPAMDToolChain only supports sanitizers in the sense that it allows
+ // sanitizer arguments on the command line if they are supported by the host
+ // toolchain. The HIPAMDToolChain will actually ignore any command line
+ // arguments for any of these "supported" sanitizers. That means that no
+ // sanitization of device code is actually supported at this time.
+ //
+ // This behavior is necessary because the host and device toolchains
+ // invocations often share the command line, so the device toolchain must
+ // tolerate flags meant only for the host toolchain.
+ return HostTC.getSupportedSanitizers();
+}
+
+VersionTuple HIPAMDToolChain::computeMSVCVersion(const Driver *D,
+ const ArgList &Args) const {
+ return HostTC.computeMSVCVersion(D, Args);
+}
+
+llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
+HIPAMDToolChain::getDeviceLibs(const llvm::opt::ArgList &DriverArgs) const {
+ llvm::SmallVector<BitCodeLibraryInfo, 12> BCLibs;
+ if (DriverArgs.hasArg(options::OPT_nogpulib))
+ return {};
+ ArgStringList LibraryPaths;
+
+ // Find in --hip-device-lib-path and HIP_LIBRARY_PATH.
+ for (StringRef Path : RocmInstallation->getRocmDeviceLibPathArg())
+ LibraryPaths.push_back(DriverArgs.MakeArgString(Path));
+
+ addDirectoryList(DriverArgs, LibraryPaths, "", "HIP_DEVICE_LIB_PATH");
+
+ // Maintain compatability with --hip-device-lib.
+ auto BCLibArgs = DriverArgs.getAllArgValues(options::OPT_hip_device_lib_EQ);
+ if (!BCLibArgs.empty()) {
+ llvm::for_each(BCLibArgs, [&](StringRef BCName) {
+ StringRef FullName;
+ for (StringRef LibraryPath : LibraryPaths) {
+ SmallString<128> Path(LibraryPath);
+ llvm::sys::path::append(Path, BCName);
+ FullName = Path;
+ if (llvm::sys::fs::exists(FullName)) {
+ BCLibs.push_back(FullName);
+ return;
+ }
+ }
+ getDriver().Diag(diag::err_drv_no_such_file) << BCName;
+ });
+ } else {
+ if (!RocmInstallation->hasDeviceLibrary()) {
+ getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 0;
+ return {};
+ }
+ StringRef GpuArch = getGPUArch(DriverArgs);
+ assert(!GpuArch.empty() && "Must have an explicit GPU arch.");
+
+ // If --hip-device-lib is not set, add the default bitcode libraries.
+ if (DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
+ options::OPT_fno_gpu_sanitize, true) &&
+ getSanitizerArgs(DriverArgs).needsAsanRt()) {
+ auto AsanRTL = RocmInstallation->getAsanRTLPath();
+ if (AsanRTL.empty()) {
+ unsigned DiagID = getDriver().getDiags().getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "AMDGPU address sanitizer runtime library (asanrtl) is not found. "
+ "Please install ROCm device library which supports address "
+ "sanitizer");
+ getDriver().Diag(DiagID);
+ return {};
+ } else
+ BCLibs.emplace_back(AsanRTL, /*ShouldInternalize=*/false);
+ }
+
+ // Add the HIP specific bitcode library.
+ BCLibs.push_back(RocmInstallation->getHIPPath());
+
+ // Add common device libraries like ocml etc.
+ for (StringRef N : getCommonDeviceLibNames(DriverArgs, GpuArch.str()))
+ BCLibs.emplace_back(N);
+
+ // Add instrument lib.
+ auto InstLib =
+ DriverArgs.getLastArgValue(options::OPT_gpu_instrument_lib_EQ);
+ if (InstLib.empty())
+ return BCLibs;
+ if (llvm::sys::fs::exists(InstLib))
+ BCLibs.push_back(InstLib);
+ else
+ getDriver().Diag(diag::err_drv_no_such_file) << InstLib;
+ }
+
+ return BCLibs;
+}
+
+void HIPAMDToolChain::checkTargetID(
+ const llvm::opt::ArgList &DriverArgs) const {
+ auto PTID = getParsedTargetID(DriverArgs);
+ if (PTID.OptionalTargetID && !PTID.OptionalGPUArch) {
+ getDriver().Diag(clang::diag::err_drv_bad_target_id)
+ << *PTID.OptionalTargetID;
+ }
+}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/HIP.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/HIPAMD.h
index 3cced0a320dc..d81a9733014c 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/HIP.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/HIPAMD.h
@@ -1,4 +1,4 @@
-//===--- HIP.h - HIP ToolChain Implementations ------------------*- C++ -*-===//
+//===--- HIPAMD.h - HIP ToolChain Implementations ---------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,12 +6,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HIP_H
-#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HIP_H
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HIPAMD_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HIPAMD_H
-#include "clang/Driver/ToolChain.h"
-#include "clang/Driver/Tool.h"
#include "AMDGPU.h"
+#include "clang/Driver/Tool.h"
+#include "clang/Driver/ToolChain.h"
namespace clang {
namespace driver {
@@ -19,14 +19,9 @@ namespace driver {
namespace tools {
namespace AMDGCN {
- // Construct command for creating HIP fatbin.
- void constructHIPFatbinCommand(Compilation &C, const JobAction &JA,
- StringRef OutputFileName, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs, const Tool& T);
-
// Runs llvm-link/opt/llc/lld, which links multiple LLVM bitcode, together with
// device library, then compiles it to ISA in a shared object.
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
public:
Linker(const ToolChain &TC) : Tool("AMDGCN::Linker", "amdgcn-link", TC) {}
@@ -38,17 +33,13 @@ public:
const char *LinkingOutput) const override;
private:
-
void constructLldCommand(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs, const InputInfo &Output,
const llvm::opt::ArgList &Args) const;
-
- // Construct command for creating Object from HIP fatbin.
- void constructGenerateObjFileFromHIPFatBinary(Compilation &C,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const llvm::opt::ArgList &Args,
- const JobAction &JA) const;
+ void constructLlvmLinkCommand(Compilation &C, const JobAction &JA,
+ const InputInfoList &Inputs,
+ const InputInfo &Output,
+ const llvm::opt::ArgList &Args) const;
};
} // end namespace AMDGCN
@@ -56,10 +47,10 @@ private:
namespace toolchains {
-class LLVM_LIBRARY_VISIBILITY HIPToolChain final : public ROCMToolChain {
+class LLVM_LIBRARY_VISIBILITY HIPAMDToolChain final : public ROCMToolChain {
public:
- HIPToolChain(const Driver &D, const llvm::Triple &Triple,
- const ToolChain &HostTC, const llvm::opt::ArgList &Args);
+ HIPAMDToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ToolChain &HostTC, const llvm::opt::ArgList &Args);
const llvm::Triple *getAuxTriple() const override {
return &HostTC.getTriple();
@@ -68,9 +59,10 @@ public:
llvm::opt::DerivedArgList *
TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
Action::OffloadKind DeviceOffloadKind) const override;
- void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args,
- Action::OffloadKind DeviceOffloadKind) const override;
+ void
+ addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadKind) const override;
void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
void
@@ -83,8 +75,8 @@ 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>
- getHIPDeviceLibs(const llvm::opt::ArgList &Args) const override;
+ llvm::SmallVector<BitCodeLibraryInfo, 12>
+ getDeviceLibs(const llvm::opt::ArgList &Args) const override;
SanitizerMask getSupportedSanitizers() const override;
@@ -92,7 +84,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;
@@ -105,4 +97,4 @@ protected:
} // end namespace driver
} // end namespace clang
-#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HIP_H
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HIPAMD_H
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/HIPSPV.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/HIPSPV.cpp
new file mode 100644
index 000000000000..a144b28057f4
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/HIPSPV.cpp
@@ -0,0 +1,288 @@
+//===--- HIPSPV.cpp - HIPSPV ToolChain Implementation -----------*- 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 "HIPSPV.h"
+#include "CommonArgs.h"
+#include "HIPUtility.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/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+// Convenience function for creating temporary file for both modes of
+// isSaveTempsEnabled().
+static const char *getTempFile(Compilation &C, StringRef Prefix,
+ StringRef Extension) {
+ if (C.getDriver().isSaveTempsEnabled()) {
+ return C.getArgs().MakeArgString(Prefix + "." + Extension);
+ }
+ auto TmpFile = C.getDriver().GetTemporaryPath(Prefix, Extension);
+ return C.addTempFile(C.getArgs().MakeArgString(TmpFile));
+}
+
+// Locates HIP pass plugin.
+static std::string findPassPlugin(const Driver &D,
+ const llvm::opt::ArgList &Args) {
+ StringRef Path = Args.getLastArgValue(options::OPT_hipspv_pass_plugin_EQ);
+ if (!Path.empty()) {
+ if (llvm::sys::fs::exists(Path))
+ return Path.str();
+ D.Diag(diag::err_drv_no_such_file) << Path;
+ }
+
+ StringRef hipPath = Args.getLastArgValue(options::OPT_hip_path_EQ);
+ if (!hipPath.empty()) {
+ SmallString<128> PluginPath(hipPath);
+ llvm::sys::path::append(PluginPath, "lib", "libLLVMHipSpvPasses.so");
+ if (llvm::sys::fs::exists(PluginPath))
+ return PluginPath.str().str();
+ PluginPath.assign(hipPath);
+ llvm::sys::path::append(PluginPath, "lib", "llvm",
+ "libLLVMHipSpvPasses.so");
+ if (llvm::sys::fs::exists(PluginPath))
+ return PluginPath.str().str();
+ }
+
+ return std::string();
+}
+
+void HIPSPV::Linker::constructLinkAndEmitSpirvCommand(
+ Compilation &C, const JobAction &JA, const InputInfoList &Inputs,
+ const InputInfo &Output, const llvm::opt::ArgList &Args) const {
+
+ assert(!Inputs.empty() && "Must have at least one input.");
+ std::string Name = std::string(llvm::sys::path::stem(Output.getFilename()));
+ const char *TempFile = getTempFile(C, Name + "-link", "bc");
+
+ // Link LLVM bitcode.
+ ArgStringList LinkArgs{};
+ for (auto Input : Inputs)
+ LinkArgs.push_back(Input.getFilename());
+ LinkArgs.append({"-o", TempFile});
+ const char *LlvmLink =
+ Args.MakeArgString(getToolChain().GetProgramPath("llvm-link"));
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ LlvmLink, LinkArgs, Inputs, Output));
+
+ // Post-link HIP lowering.
+
+ // Run LLVM IR passes to lower/expand/emulate HIP code that does not translate
+ // to SPIR-V (E.g. dynamic shared memory).
+ auto PassPluginPath = findPassPlugin(C.getDriver(), Args);
+ if (!PassPluginPath.empty()) {
+ const char *PassPathCStr = C.getArgs().MakeArgString(PassPluginPath);
+ const char *OptOutput = getTempFile(C, Name + "-lower", "bc");
+ ArgStringList OptArgs{TempFile, "-load-pass-plugin",
+ PassPathCStr, "-passes=hip-post-link-passes",
+ "-o", OptOutput};
+ const char *Opt = Args.MakeArgString(getToolChain().GetProgramPath("opt"));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::None(), Opt, OptArgs, Inputs, Output));
+ TempFile = OptOutput;
+ }
+
+ // Emit SPIR-V binary.
+
+ llvm::opt::ArgStringList TrArgs{"--spirv-max-version=1.1",
+ "--spirv-ext=+all"};
+ InputInfo TrInput = InputInfo(types::TY_LLVM_BC, TempFile, "");
+ SPIRV::constructTranslateCommand(C, *this, JA, Output, TrInput, TrArgs);
+}
+
+void HIPSPV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ if (Inputs.size() > 0 && Inputs[0].getType() == types::TY_Image &&
+ JA.getType() == types::TY_Object)
+ return HIP::constructGenerateObjFileFromHIPFatBinary(C, Output, Inputs,
+ Args, JA, *this);
+
+ if (JA.getType() == types::TY_HIP_FATBIN)
+ return HIP::constructHIPFatbinCommand(C, JA, Output.getFilename(), Inputs,
+ Args, *this);
+
+ constructLinkAndEmitSpirvCommand(C, JA, Inputs, Output, Args);
+}
+
+HIPSPVToolChain::HIPSPVToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ToolChain &HostTC, const ArgList &Args)
+ : ToolChain(D, Triple, Args), HostTC(HostTC) {
+ // Lookup binaries into the driver directory, this is used to
+ // discover the clang-offload-bundler executable.
+ getProgramPaths().push_back(getDriver().Dir);
+}
+
+void HIPSPVToolChain::addClangTargetOptions(
+ const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadingKind) const {
+ HostTC.addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadingKind);
+
+ assert(DeviceOffloadingKind == Action::OFK_HIP &&
+ "Only HIP offloading kinds are supported for GPUs.");
+
+ CC1Args.append(
+ {"-fcuda-is-device", "-fcuda-allow-variadic-functions",
+ // A crude workaround for llvm-spirv which does not handle the
+ // autovectorized code well (vector reductions, non-i{8,16,32,64} types).
+ // TODO: Allow autovectorization when SPIR-V backend arrives.
+ "-mllvm", "-vectorize-loops=false", "-mllvm", "-vectorize-slp=false"});
+
+ // Default to "hidden" visibility, as object level linking will not be
+ // supported for the foreseeable future.
+ if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
+ options::OPT_fvisibility_ms_compat))
+ CC1Args.append(
+ {"-fvisibility=hidden", "-fapply-global-visibility-to-externs"});
+
+ llvm::for_each(getDeviceLibs(DriverArgs),
+ [&](const BitCodeLibraryInfo &BCFile) {
+ CC1Args.append({"-mlink-builtin-bitcode",
+ DriverArgs.MakeArgString(BCFile.Path)});
+ });
+}
+
+Tool *HIPSPVToolChain::buildLinker() const {
+ assert(getTriple().getArch() == llvm::Triple::spirv64);
+ return new tools::HIPSPV::Linker(*this);
+}
+
+void HIPSPVToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {
+ HostTC.addClangWarningOptions(CC1Args);
+}
+
+ToolChain::CXXStdlibType
+HIPSPVToolChain::GetCXXStdlibType(const ArgList &Args) const {
+ return HostTC.GetCXXStdlibType(Args);
+}
+
+void HIPSPVToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ HostTC.AddClangSystemIncludeArgs(DriverArgs, CC1Args);
+}
+
+void HIPSPVToolChain::AddClangCXXStdlibIncludeArgs(
+ const ArgList &Args, ArgStringList &CC1Args) const {
+ HostTC.AddClangCXXStdlibIncludeArgs(Args, CC1Args);
+}
+
+void HIPSPVToolChain::AddIAMCUIncludeArgs(const ArgList &Args,
+ ArgStringList &CC1Args) const {
+ HostTC.AddIAMCUIncludeArgs(Args, CC1Args);
+}
+
+void HIPSPVToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nogpuinc))
+ return;
+
+ StringRef hipPath = DriverArgs.getLastArgValue(options::OPT_hip_path_EQ);
+ if (hipPath.empty()) {
+ getDriver().Diag(diag::err_drv_hipspv_no_hip_path) << 1 << "'-nogpuinc'";
+ return;
+ }
+ SmallString<128> P(hipPath);
+ llvm::sys::path::append(P, "include");
+ CC1Args.append({"-isystem", DriverArgs.MakeArgString(P)});
+}
+
+llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
+HIPSPVToolChain::getDeviceLibs(const llvm::opt::ArgList &DriverArgs) const {
+ llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12> BCLibs;
+ if (DriverArgs.hasArg(options::OPT_nogpulib))
+ return {};
+
+ ArgStringList LibraryPaths;
+ // Find device libraries in --hip-device-lib-path and HIP_DEVICE_LIB_PATH.
+ auto HipDeviceLibPathArgs = DriverArgs.getAllArgValues(
+ // --hip-device-lib-path is alias to this option.
+ clang::driver::options::OPT_rocm_device_lib_path_EQ);
+ for (auto Path : HipDeviceLibPathArgs)
+ LibraryPaths.push_back(DriverArgs.MakeArgString(Path));
+
+ StringRef HipPath = DriverArgs.getLastArgValue(options::OPT_hip_path_EQ);
+ if (!HipPath.empty()) {
+ SmallString<128> Path(HipPath);
+ llvm::sys::path::append(Path, "lib", "hip-device-lib");
+ LibraryPaths.push_back(DriverArgs.MakeArgString(Path));
+ }
+
+ addDirectoryList(DriverArgs, LibraryPaths, "", "HIP_DEVICE_LIB_PATH");
+
+ // Maintain compatability with --hip-device-lib.
+ auto BCLibArgs = DriverArgs.getAllArgValues(options::OPT_hip_device_lib_EQ);
+ if (!BCLibArgs.empty()) {
+ llvm::for_each(BCLibArgs, [&](StringRef BCName) {
+ StringRef FullName;
+ for (std::string LibraryPath : LibraryPaths) {
+ SmallString<128> Path(LibraryPath);
+ llvm::sys::path::append(Path, BCName);
+ FullName = Path;
+ if (llvm::sys::fs::exists(FullName)) {
+ BCLibs.emplace_back(FullName.str());
+ return;
+ }
+ }
+ getDriver().Diag(diag::err_drv_no_such_file) << BCName;
+ });
+ } else {
+ // Search device library named as 'hipspv-<triple>.bc'.
+ auto TT = getTriple().normalize();
+ std::string BCName = "hipspv-" + TT + ".bc";
+ for (auto *LibPath : LibraryPaths) {
+ SmallString<128> Path(LibPath);
+ llvm::sys::path::append(Path, BCName);
+ if (llvm::sys::fs::exists(Path)) {
+ BCLibs.emplace_back(Path.str().str());
+ return BCLibs;
+ }
+ }
+ getDriver().Diag(diag::err_drv_no_hipspv_device_lib)
+ << 1 << ("'" + TT + "' target");
+ return {};
+ }
+
+ return BCLibs;
+}
+
+SanitizerMask HIPSPVToolChain::getSupportedSanitizers() const {
+ // The HIPSPVToolChain only supports sanitizers in the sense that it allows
+ // sanitizer arguments on the command line if they are supported by the host
+ // toolchain. The HIPSPVToolChain will actually ignore any command line
+ // arguments for any of these "supported" sanitizers. That means that no
+ // sanitization of device code is actually supported at this time.
+ //
+ // This behavior is necessary because the host and device toolchains
+ // invocations often share the command line, so the device toolchain must
+ // tolerate flags meant only for the host toolchain.
+ return HostTC.getSupportedSanitizers();
+}
+
+VersionTuple HIPSPVToolChain::computeMSVCVersion(const Driver *D,
+ const ArgList &Args) const {
+ return HostTC.computeMSVCVersion(D, Args);
+}
+
+void HIPSPVToolChain::adjustDebugInfoKind(
+ llvm::codegenoptions::DebugInfoKind &DebugInfoKind,
+ const llvm::opt::ArgList &Args) const {
+ // Debug info generation is disabled for SPIRV-LLVM-Translator
+ // which currently aborts on the presence of DW_OP_LLVM_convert.
+ // TODO: Enable debug info when the SPIR-V backend arrives.
+ DebugInfoKind = llvm::codegenoptions::NoDebugInfo;
+}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/HIPSPV.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/HIPSPV.h
new file mode 100644
index 000000000000..ecd82e7052e4
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/HIPSPV.h
@@ -0,0 +1,102 @@
+//===--- HIPSPV.h - HIP ToolChain Implementations ---------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HIPSPV_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HIPSPV_H
+
+#include "SPIRV.h"
+#include "clang/Driver/Tool.h"
+#include "clang/Driver/ToolChain.h"
+
+namespace clang {
+namespace driver {
+namespace tools {
+namespace HIPSPV {
+
+// Runs llvm-link/opt/llc/lld, which links multiple LLVM bitcode, together with
+// device library, then compiles it to SPIR-V in a shared object.
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
+public:
+ Linker(const ToolChain &TC) : Tool("HIPSPV::Linker", "hipspv-link", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+
+private:
+ void constructLinkAndEmitSpirvCommand(Compilation &C, const JobAction &JA,
+ const InputInfoList &Inputs,
+ const InputInfo &Output,
+ const llvm::opt::ArgList &Args) const;
+};
+
+} // namespace HIPSPV
+} // namespace tools
+
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY HIPSPVToolChain final : public ToolChain {
+public:
+ HIPSPVToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ToolChain &HostTC, const llvm::opt::ArgList &Args);
+
+ const llvm::Triple *getAuxTriple() const override {
+ return &HostTC.getTriple();
+ }
+
+ void
+ addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadKind) const override;
+ void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;
+ CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ llvm::SmallVector<BitCodeLibraryInfo, 12>
+ getDeviceLibs(const llvm::opt::ArgList &Args) const override;
+
+ SanitizerMask getSupportedSanitizers() const override;
+
+ VersionTuple
+ computeMSVCVersion(const Driver *D,
+ const llvm::opt::ArgList &Args) const override;
+
+ void adjustDebugInfoKind(llvm::codegenoptions::DebugInfoKind &DebugInfoKind,
+ const llvm::opt::ArgList &Args) const override;
+ 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 llvm::opt::ArgList &Args) const override {
+ return false;
+ }
+ bool isPICDefaultForced() const override { return false; }
+ bool SupportsProfiling() const override { return false; }
+
+ const ToolChain &HostTC;
+
+protected:
+ Tool *buildLinker() const override;
+};
+
+} // end namespace toolchains
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HIPSPV_H
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/HIPUtility.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/HIPUtility.cpp
new file mode 100644
index 000000000000..f692458b775d
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/HIPUtility.cpp
@@ -0,0 +1,179 @@
+//===--- HIPUtility.cpp - Common HIP Tool Chain Utilities -------*- 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 "HIPUtility.h"
+#include "CommonArgs.h"
+#include "clang/Driver/Compilation.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Path.h"
+#include "llvm/TargetParser/Triple.h"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace llvm::opt;
+
+#if defined(_WIN32) || defined(_WIN64)
+#define NULL_FILE "nul"
+#else
+#define NULL_FILE "/dev/null"
+#endif
+
+namespace {
+const unsigned HIPCodeObjectAlign = 4096;
+} // namespace
+
+// Constructs a triple string for clang offload bundler.
+static std::string normalizeForBundler(const llvm::Triple &T,
+ bool HasTargetID) {
+ return HasTargetID ? (T.getArchName() + "-" + T.getVendorName() + "-" +
+ T.getOSName() + "-" + T.getEnvironmentName())
+ .str()
+ : T.normalize();
+}
+
+// Construct a clang-offload-bundler command to bundle code objects for
+// different devices into a HIP fat binary.
+void HIP::constructHIPFatbinCommand(Compilation &C, const JobAction &JA,
+ llvm::StringRef OutputFileName,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &Args,
+ const Tool &T) {
+ // Construct clang-offload-bundler command to bundle object files for
+ // for different GPU archs.
+ ArgStringList BundlerArgs;
+ BundlerArgs.push_back(Args.MakeArgString("-type=o"));
+ BundlerArgs.push_back(
+ Args.MakeArgString("-bundle-align=" + Twine(HIPCodeObjectAlign)));
+
+ // ToDo: Remove the dummy host binary entry which is required by
+ // clang-offload-bundler.
+ std::string BundlerTargetArg = "-targets=host-x86_64-unknown-linux";
+ // AMDGCN:
+ // For code object version 2 and 3, the offload kind in bundle ID is 'hip'
+ // for backward compatibility. For code object version 4 and greater, the
+ // offload kind in bundle ID is 'hipv4'.
+ std::string OffloadKind = "hip";
+ auto &TT = T.getToolChain().getTriple();
+ if (TT.isAMDGCN() && getAMDGPUCodeObjectVersion(C.getDriver(), Args) >= 4)
+ OffloadKind = OffloadKind + "v4";
+ for (const auto &II : Inputs) {
+ const auto *A = II.getAction();
+ auto ArchStr = llvm::StringRef(A->getOffloadingArch());
+ BundlerTargetArg +=
+ "," + OffloadKind + "-" + normalizeForBundler(TT, !ArchStr.empty());
+ if (!ArchStr.empty())
+ BundlerTargetArg += "-" + ArchStr.str();
+ }
+ BundlerArgs.push_back(Args.MakeArgString(BundlerTargetArg));
+
+ // Use a NULL file as input for the dummy host binary entry
+ std::string BundlerInputArg = "-input=" NULL_FILE;
+ BundlerArgs.push_back(Args.MakeArgString(BundlerInputArg));
+ for (const auto &II : Inputs) {
+ BundlerInputArg = std::string("-input=") + II.getFilename();
+ BundlerArgs.push_back(Args.MakeArgString(BundlerInputArg));
+ }
+
+ std::string Output = std::string(OutputFileName);
+ auto *BundlerOutputArg =
+ Args.MakeArgString(std::string("-output=").append(Output));
+ BundlerArgs.push_back(BundlerOutputArg);
+
+ if (Args.hasFlag(options::OPT_offload_compress,
+ options::OPT_no_offload_compress, false))
+ BundlerArgs.push_back("-compress");
+ if (Args.hasArg(options::OPT_v))
+ BundlerArgs.push_back("-verbose");
+
+ const char *Bundler = Args.MakeArgString(
+ T.getToolChain().GetProgramPath("clang-offload-bundler"));
+ C.addCommand(std::make_unique<Command>(
+ JA, T, ResponseFileSupport::None(), Bundler, BundlerArgs, Inputs,
+ InputInfo(&JA, Args.MakeArgString(Output))));
+}
+
+/// Add Generated HIP Object File which has device images embedded into the
+/// host to the argument list for linking. Using MC directives, embed the
+/// device code and also define symbols required by the code generation so that
+/// the image can be retrieved at runtime.
+void HIP::constructGenerateObjFileFromHIPFatBinary(
+ Compilation &C, const InputInfo &Output, const InputInfoList &Inputs,
+ const ArgList &Args, const JobAction &JA, const Tool &T) {
+ const ToolChain &TC = T.getToolChain();
+ std::string Name = std::string(llvm::sys::path::stem(Output.getFilename()));
+
+ // Create Temp Object File Generator,
+ // Offload Bundled file and Bundled Object file.
+ // Keep them if save-temps is enabled.
+ const char *McinFile;
+ const char *BundleFile;
+ if (C.getDriver().isSaveTempsEnabled()) {
+ McinFile = C.getArgs().MakeArgString(Name + ".mcin");
+ BundleFile = C.getArgs().MakeArgString(Name + ".hipfb");
+ } else {
+ auto TmpNameMcin = C.getDriver().GetTemporaryPath(Name, "mcin");
+ McinFile = C.addTempFile(C.getArgs().MakeArgString(TmpNameMcin));
+ auto TmpNameFb = C.getDriver().GetTemporaryPath(Name, "hipfb");
+ BundleFile = C.addTempFile(C.getArgs().MakeArgString(TmpNameFb));
+ }
+ HIP::constructHIPFatbinCommand(C, JA, BundleFile, Inputs, Args, T);
+
+ // Create a buffer to write the contents of the temp obj generator.
+ std::string ObjBuffer;
+ llvm::raw_string_ostream ObjStream(ObjBuffer);
+
+ auto HostTriple =
+ C.getSingleOffloadToolChain<Action::OFK_Host>()->getTriple();
+
+ // Add MC directives to embed target binaries. We ensure that each
+ // section and image is 16-byte aligned. This is not mandatory, but
+ // increases the likelihood of data to be aligned with a cache block
+ // in several main host machines.
+ ObjStream << "# HIP Object Generator\n";
+ ObjStream << "# *** Automatically generated by Clang ***\n";
+ if (HostTriple.isWindowsMSVCEnvironment()) {
+ ObjStream << " .section .hip_fatbin, \"dw\"\n";
+ } else {
+ ObjStream << " .protected __hip_fatbin\n";
+ ObjStream << " .type __hip_fatbin,@object\n";
+ ObjStream << " .section .hip_fatbin,\"a\",@progbits\n";
+ }
+ ObjStream << " .globl __hip_fatbin\n";
+ ObjStream << " .p2align " << llvm::Log2(llvm::Align(HIPCodeObjectAlign))
+ << "\n";
+ ObjStream << "__hip_fatbin:\n";
+ ObjStream << " .incbin ";
+ llvm::sys::printArg(ObjStream, BundleFile, /*Quote=*/true);
+ ObjStream << "\n";
+ if (HostTriple.isOSLinux() && HostTriple.isOSBinFormatELF())
+ ObjStream << " .section .note.GNU-stack, \"\", @progbits\n";
+ ObjStream.flush();
+
+ // Dump the contents of the temp object file gen if the user requested that.
+ // We support this option to enable testing of behavior with -###.
+ if (C.getArgs().hasArg(options::OPT_fhip_dump_offload_linker_script))
+ llvm::errs() << ObjBuffer;
+
+ // Open script file and write the contents.
+ std::error_code EC;
+ llvm::raw_fd_ostream Objf(McinFile, EC, llvm::sys::fs::OF_None);
+
+ if (EC) {
+ C.getDriver().Diag(clang::diag::err_unable_to_make_temp) << EC.message();
+ return;
+ }
+
+ Objf << ObjBuffer;
+
+ ArgStringList McArgs{"-triple", Args.MakeArgString(HostTriple.normalize()),
+ "-o", Output.getFilename(),
+ McinFile, "--filetype=obj"};
+ const char *Mc = Args.MakeArgString(TC.GetProgramPath("llvm-mc"));
+ C.addCommand(std::make_unique<Command>(JA, T, ResponseFileSupport::None(), Mc,
+ McArgs, Inputs, Output));
+}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/HIPUtility.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/HIPUtility.h
new file mode 100644
index 000000000000..29e5a922024a
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/HIPUtility.h
@@ -0,0 +1,35 @@
+//===--- HIPUtility.h - Common HIP Tool Chain Utilities ---------*- 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_HIPUTILITY_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HIPUTILITY_H
+
+#include "clang/Driver/Tool.h"
+
+namespace clang {
+namespace driver {
+namespace tools {
+namespace HIP {
+
+// Construct command for creating HIP fatbin.
+void constructHIPFatbinCommand(Compilation &C, const JobAction &JA,
+ StringRef OutputFileName,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs, const Tool &T);
+
+// Construct command for creating Object from HIP fatbin.
+void constructGenerateObjFileFromHIPFatBinary(
+ Compilation &C, const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &Args, const JobAction &JA, const Tool &T);
+
+} // namespace HIP
+} // namespace tools
+} // namespace driver
+} // namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HIPUTILITY_H
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/HLSL.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/HLSL.cpp
new file mode 100644
index 000000000000..c6ad862b2294
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/HLSL.cpp
@@ -0,0 +1,259 @@
+//===--- HLSL.cpp - HLSL ToolChain Implementations --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "HLSL.h"
+#include "CommonArgs.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Job.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/TargetParser/Triple.h"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang::driver::toolchains;
+using namespace clang;
+using namespace llvm::opt;
+using namespace llvm;
+
+namespace {
+
+const unsigned OfflineLibMinor = 0xF;
+
+bool isLegalShaderModel(Triple &T) {
+ if (T.getOS() != Triple::OSType::ShaderModel)
+ return false;
+
+ auto Version = T.getOSVersion();
+ if (Version.getBuild())
+ return false;
+ if (Version.getSubminor())
+ return false;
+
+ auto Kind = T.getEnvironment();
+
+ switch (Kind) {
+ default:
+ return false;
+ case Triple::EnvironmentType::Vertex:
+ case Triple::EnvironmentType::Hull:
+ case Triple::EnvironmentType::Domain:
+ case Triple::EnvironmentType::Geometry:
+ case Triple::EnvironmentType::Pixel:
+ case Triple::EnvironmentType::Compute: {
+ VersionTuple MinVer(4, 0);
+ return MinVer <= Version;
+ } break;
+ case Triple::EnvironmentType::Library: {
+ VersionTuple SM6x(6, OfflineLibMinor);
+ if (Version == SM6x)
+ return true;
+
+ VersionTuple MinVer(6, 3);
+ return MinVer <= Version;
+ } break;
+ case Triple::EnvironmentType::Amplification:
+ case Triple::EnvironmentType::Mesh: {
+ VersionTuple MinVer(6, 5);
+ return MinVer <= Version;
+ } break;
+ }
+ return false;
+}
+
+std::optional<std::string> tryParseProfile(StringRef Profile) {
+ // [ps|vs|gs|hs|ds|cs|ms|as]_[major]_[minor]
+ SmallVector<StringRef, 3> Parts;
+ Profile.split(Parts, "_");
+ if (Parts.size() != 3)
+ return std::nullopt;
+
+ Triple::EnvironmentType Kind =
+ StringSwitch<Triple::EnvironmentType>(Parts[0])
+ .Case("ps", Triple::EnvironmentType::Pixel)
+ .Case("vs", Triple::EnvironmentType::Vertex)
+ .Case("gs", Triple::EnvironmentType::Geometry)
+ .Case("hs", Triple::EnvironmentType::Hull)
+ .Case("ds", Triple::EnvironmentType::Domain)
+ .Case("cs", Triple::EnvironmentType::Compute)
+ .Case("lib", Triple::EnvironmentType::Library)
+ .Case("ms", Triple::EnvironmentType::Mesh)
+ .Case("as", Triple::EnvironmentType::Amplification)
+ .Default(Triple::EnvironmentType::UnknownEnvironment);
+ if (Kind == Triple::EnvironmentType::UnknownEnvironment)
+ return std::nullopt;
+
+ unsigned long long Major = 0;
+ if (llvm::getAsUnsignedInteger(Parts[1], 0, Major))
+ return std::nullopt;
+
+ unsigned long long Minor = 0;
+ if (Parts[2] == "x" && Kind == Triple::EnvironmentType::Library)
+ Minor = OfflineLibMinor;
+ else if (llvm::getAsUnsignedInteger(Parts[2], 0, Minor))
+ return std::nullopt;
+
+ // dxil-unknown-shadermodel-hull
+ llvm::Triple T;
+ T.setArch(Triple::ArchType::dxil);
+ T.setOSName(Triple::getOSTypeName(Triple::OSType::ShaderModel).str() +
+ VersionTuple(Major, Minor).getAsString());
+ T.setEnvironment(Kind);
+ if (isLegalShaderModel(T))
+ return T.getTriple();
+ else
+ return std::nullopt;
+}
+
+bool isLegalValidatorVersion(StringRef ValVersionStr, const Driver &D) {
+ VersionTuple Version;
+ if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
+ Version.getSubminor() || !Version.getMinor()) {
+ D.Diag(diag::err_drv_invalid_format_dxil_validator_version)
+ << ValVersionStr;
+ return false;
+ }
+
+ uint64_t Major = Version.getMajor();
+ uint64_t Minor = *Version.getMinor();
+ if (Major == 0 && Minor != 0) {
+ D.Diag(diag::err_drv_invalid_empty_dxil_validator_version) << ValVersionStr;
+ return false;
+ }
+ VersionTuple MinVer(1, 0);
+ if (Version < MinVer) {
+ D.Diag(diag::err_drv_invalid_range_dxil_validator_version) << ValVersionStr;
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
+void tools::hlsl::Validator::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ std::string DxvPath = getToolChain().GetProgramPath("dxv");
+ assert(DxvPath != "dxv" && "cannot find dxv");
+
+ ArgStringList CmdArgs;
+ assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
+ const InputInfo &Input = Inputs[0];
+ assert(Input.isFilename() && "Unexpected verify input");
+ // Grabbing the output of the earlier cc1 run.
+ CmdArgs.push_back(Input.getFilename());
+ // Use the same name as output.
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Input.getFilename());
+
+ const char *Exec = Args.MakeArgString(DxvPath);
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Exec, CmdArgs, Inputs, Input));
+}
+
+/// DirectX Toolchain
+HLSLToolChain::HLSLToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : ToolChain(D, Triple, Args) {
+ if (Args.hasArg(options::OPT_dxc_validator_path_EQ))
+ getProgramPaths().push_back(
+ Args.getLastArgValue(options::OPT_dxc_validator_path_EQ).str());
+}
+
+Tool *clang::driver::toolchains::HLSLToolChain::getTool(
+ Action::ActionClass AC) const {
+ switch (AC) {
+ case Action::BinaryAnalyzeJobClass:
+ if (!Validator)
+ Validator.reset(new tools::hlsl::Validator(*this));
+ return Validator.get();
+ default:
+ return ToolChain::getTool(AC);
+ }
+}
+
+std::optional<std::string>
+clang::driver::toolchains::HLSLToolChain::parseTargetProfile(
+ StringRef TargetProfile) {
+ return tryParseProfile(TargetProfile);
+}
+
+DerivedArgList *
+HLSLToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind) const {
+ DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
+
+ const OptTable &Opts = getDriver().getOpts();
+
+ for (Arg *A : Args) {
+ if (A->getOption().getID() == options::OPT_dxil_validator_version) {
+ StringRef ValVerStr = A->getValue();
+ std::string ErrorMsg;
+ if (!isLegalValidatorVersion(ValVerStr, getDriver()))
+ continue;
+ }
+ if (A->getOption().getID() == options::OPT_dxc_entrypoint) {
+ DAL->AddSeparateArg(nullptr, Opts.getOption(options::OPT_hlsl_entrypoint),
+ A->getValue());
+ A->claim();
+ continue;
+ }
+ if (A->getOption().getID() == options::OPT__SLASH_O) {
+ StringRef OStr = A->getValue();
+ if (OStr == "d") {
+ DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_O0));
+ A->claim();
+ continue;
+ } else {
+ DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_O), OStr);
+ A->claim();
+ continue;
+ }
+ }
+ if (A->getOption().getID() == options::OPT_emit_pristine_llvm) {
+ // Translate fcgl into -S -emit-llvm and -disable-llvm-passes.
+ DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_S));
+ DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_emit_llvm));
+ DAL->AddFlagArg(nullptr,
+ Opts.getOption(options::OPT_disable_llvm_passes));
+ A->claim();
+ continue;
+ }
+ DAL->append(A);
+ }
+
+ // Add default validator version if not set.
+ // TODO: remove this once read validator version from validator.
+ if (!DAL->hasArg(options::OPT_dxil_validator_version)) {
+ const StringRef DefaultValidatorVer = "1.7";
+ DAL->AddSeparateArg(nullptr,
+ Opts.getOption(options::OPT_dxil_validator_version),
+ DefaultValidatorVer);
+ }
+ if (!DAL->hasArg(options::OPT_O_Group)) {
+ DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_O), "3");
+ }
+ // FIXME: add validation for enable_16bit_types should be after HLSL 2018 and
+ // shader model 6.2.
+ // See: https://github.com/llvm/llvm-project/issues/57876
+ return DAL;
+}
+
+bool HLSLToolChain::requiresValidation(DerivedArgList &Args) const {
+ if (Args.getLastArg(options::OPT_dxc_disable_validation))
+ return false;
+
+ std::string DxvPath = GetProgramPath("dxv");
+ if (DxvPath != "dxv")
+ return true;
+
+ getDriver().Diag(diag::warn_drv_dxc_missing_dxv);
+ return false;
+}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/HLSL.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/HLSL.h
new file mode 100644
index 000000000000..7b775b897431
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/HLSL.h
@@ -0,0 +1,63 @@
+//===--- HLSL.h - HLSL ToolChain Implementations ----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HLSL_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HLSL_H
+
+#include "clang/Driver/Tool.h"
+#include "clang/Driver/ToolChain.h"
+
+namespace clang {
+namespace driver {
+
+namespace tools {
+
+namespace hlsl {
+class LLVM_LIBRARY_VISIBILITY Validator : public Tool {
+public:
+ Validator(const ToolChain &TC) : Tool("hlsl::Validator", "dxv", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+} // namespace hlsl
+} // namespace tools
+
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY HLSLToolChain : public ToolChain {
+public:
+ HLSLToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+ Tool *getTool(Action::ActionClass AC) const override;
+
+ bool isPICDefault() const override { return false; }
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override {
+ return false;
+ }
+ bool isPICDefaultForced() const override { return false; }
+
+ llvm::opt::DerivedArgList *
+ TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind) const override;
+ static std::optional<std::string> parseTargetProfile(StringRef TargetProfile);
+ bool requiresValidation(llvm::opt::DerivedArgList &Args) const;
+
+private:
+ mutable std::unique_ptr<tools::hlsl::Validator> Validator;
+};
+
+} // end namespace toolchains
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HLSL_H
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Haiku.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Haiku.cpp
index a79f0f7622ad..e0d94035823f 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Haiku.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Haiku.cpp
@@ -8,27 +8,272 @@
#include "Haiku.h"
#include "CommonArgs.h"
+#include "clang/Config/config.h"
+#include "clang/Driver/Compilation.h"
+#include "llvm/Support/Path.h"
using namespace clang::driver;
+using namespace clang::driver::tools;
using namespace clang::driver::toolchains;
using namespace clang;
using namespace llvm::opt;
+void haiku::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const auto &ToolChain = static_cast<const Haiku &>(getToolChain());
+ const Driver &D = ToolChain.getDriver();
+ const llvm::Triple::ArchType Arch = ToolChain.getArch();
+ const bool Static = Args.hasArg(options::OPT_static);
+ const bool Shared = Args.hasArg(options::OPT_shared);
+ ArgStringList CmdArgs;
+
+ // 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 warning for "clang -pie foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_pie);
+
+ // -rdynamic is a no-op with Haiku. Claim argument to avoid warning.
+ Args.ClaimAllArgs(options::OPT_rdynamic);
+
+ if (!D.SysRoot.empty())
+ CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+
+ CmdArgs.push_back("--eh-frame-hdr");
+ if (Static) {
+ CmdArgs.push_back("-Bstatic");
+ } else {
+ if (Shared)
+ CmdArgs.push_back("-shared");
+ CmdArgs.push_back("--enable-new-dtags");
+ }
+
+ CmdArgs.push_back("-shared");
+
+ if (!Shared)
+ CmdArgs.push_back("--no-undefined");
+
+ if (Arch == llvm::Triple::riscv64)
+ CmdArgs.push_back("-X");
+
+ assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbeginS.o")));
+ if (!Shared)
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("start_dyn.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("init_term_dyn.o")));
+ }
+
+ Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
+ options::OPT_s, options::OPT_t, options::OPT_r});
+ ToolChain.AddFilePathLibArgs(Args, CmdArgs);
+
+ if (D.isUsingLTO()) {
+ assert(!Inputs.empty() && "Must have at least one input.");
+ // Find the first filename InputInfo object.
+ auto Input = llvm::find_if(
+ Inputs, [](const InputInfo &II) -> bool { return II.isFilename(); });
+ if (Input == Inputs.end())
+ // For a very rare case, all of the inputs to the linker are
+ // InputArg. If that happens, just use the first InputInfo.
+ Input = Inputs.begin();
+
+ addLTOOptions(ToolChain, Args, CmdArgs, Output, *Input,
+ D.getLTOMode() == LTOK_Thin);
+ }
+
+ addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs);
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
+
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
+ options::OPT_r)) {
+ // Use the static OpenMP runtime with -static-openmp
+ bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Static;
+ addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP);
+
+ if (D.CCCIsCXX() && ToolChain.ShouldLinkCXXStdlib(Args))
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+
+ // Silence warnings when linking C code with a C++ '-stdlib' argument.
+ Args.ClaimAllArgs(options::OPT_stdlib_EQ);
+
+ // Additional linker set-up and flags for Fortran. This is required in order
+ // to generate executables. As Fortran runtime depends on the C runtime,
+ // these dependencies need to be listed before the C runtime below (i.e.
+ // AddRunTimeLibs).
+ if (D.IsFlangMode()) {
+ addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
+ addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
+ }
+
+ CmdArgs.push_back("-lgcc");
+
+ CmdArgs.push_back("--push-state");
+ CmdArgs.push_back("--as-needed");
+ CmdArgs.push_back("-lgcc_s");
+ CmdArgs.push_back("--no-as-needed");
+ CmdArgs.push_back("--pop-state");
+
+ CmdArgs.push_back("-lroot");
+
+ CmdArgs.push_back("-lgcc");
+
+ CmdArgs.push_back("--push-state");
+ CmdArgs.push_back("--as-needed");
+ CmdArgs.push_back("-lgcc_s");
+ CmdArgs.push_back("--no-as-needed");
+ CmdArgs.push_back("--pop-state");
+ }
+
+ // No need to do anything for pthreads. Claim argument to avoid warning.
+ Args.claimAllArgs(options::OPT_pthread, options::OPT_pthreads);
+
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
+ }
+
+ ToolChain.addProfileRTLibs(Args, CmdArgs);
+
+ const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
+ C.addCommand(std::make_unique<Command>(JA, *this,
+ ResponseFileSupport::AtFileCurCP(),
+ Exec, CmdArgs, Inputs, Output));
+}
+
/// Haiku - Haiku tool chain which can call as(1) and ld(1) directly.
Haiku::Haiku(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
+ GCCInstallation.init(Triple, Args);
+
+ getFilePaths().push_back(concat(getDriver().SysRoot, "/boot/system/lib"));
+ getFilePaths().push_back(concat(getDriver().SysRoot, "/boot/system/develop/lib"));
+
+ if (GCCInstallation.isValid())
+ getFilePaths().push_back(GCCInstallation.getInstallPath().str());
+}
+
+void Haiku::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ const Driver &D = getDriver();
+
+ if (DriverArgs.hasArg(options::OPT_nostdinc))
+ return;
+
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+ SmallString<128> Dir(D.ResourceDir);
+ llvm::sys::path::append(Dir, "include");
+ addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ }
+
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+
+ // Add dirs specified via 'configure --with-c-include-dirs'.
+ StringRef CIncludeDirs(C_INCLUDE_DIRS);
+ if (!CIncludeDirs.empty()) {
+ SmallVector<StringRef, 5> dirs;
+ CIncludeDirs.split(dirs, ":");
+ for (StringRef dir : dirs) {
+ StringRef Prefix =
+ llvm::sys::path::is_absolute(dir) ? StringRef(D.SysRoot) : "";
+ addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
+ }
+ return;
+ }
+
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/non-packaged/develop/headers"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/app"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/device"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/drivers"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/game"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/interface"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/kernel"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/locale"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/mail"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/media"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/midi"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/midi2"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/net"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/opengl"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/storage"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/support"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/translation"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/add-ons/graphics"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/add-ons/input_server"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/add-ons/mail_daemon"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/add-ons/registrar"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/add-ons/screen_saver"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/add-ons/tracker"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/be_apps/Deskbar"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/be_apps/NetPositive"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/os/be_apps/Tracker"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/3rdparty"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/bsd"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/glibc"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/gnu"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers/posix"));
+ addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
+ "/boot/system/develop/headers"));
}
void Haiku::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/system/develop/headers/c++/v1");
+ concat(getDriver().SysRoot, "/boot/system/develop/headers/c++/v1"));
}
-void Haiku::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const {
- addLibStdCXXIncludePaths(getDriver().SysRoot + "/system/develop/headers/c++",
- getTriple().str(), "", DriverArgs, CC1Args);
-}
+Tool *Haiku::buildLinker() const { return new tools::haiku::Linker(*this); }
+
+bool Haiku::HasNativeLLVMSupport() const { return true; }
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Haiku.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Haiku.h
index 2bc98322bebf..a34f76e22284 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Haiku.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Haiku.h
@@ -15,6 +15,25 @@
namespace clang {
namespace driver {
+namespace tools {
+
+/// Directly call GNU Binutils assembler and linker
+namespace haiku {
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
+public:
+ Linker(const ToolChain &TC) : Tool("haiku::Linker", "linker", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+} // end namespace haiku
+} // end namespace tools
+
namespace toolchains {
class LLVM_LIBRARY_VISIBILITY Haiku : public Generic_ELF {
@@ -22,16 +41,27 @@ public:
Haiku(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
- bool isPIEDefault() const override {
- return getTriple().getArch() == llvm::Triple::x86_64;
- }
+ bool HasNativeLLVMSupport() const override;
- void addLibCxxIncludePaths(
+ bool IsMathErrnoDefault() const override { return false; }
+ bool IsObjCNonFragileABIDefault() const override { return true; }
+ bool isPICDefault() const override { return true; }
+
+ const char *getDefaultLinker() const override { return "ld.lld"; }
+
+ void AddClangSystemIncludeArgs(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- void addLibStdCxxIncludePaths(
+ void addLibCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+
+ unsigned GetDefaultDwarfVersion() const override { return 4; }
+
+ bool GetDefaultStandaloneDebug() const override { return true; }
+
+protected:
+ Tool *buildLinker() const override;
};
} // end namespace toolchains
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Hexagon.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Hexagon.cpp
index 314d0efce441..d1eed931be5f 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Hexagon.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Hexagon.cpp
@@ -26,8 +26,8 @@ using namespace clang;
using namespace llvm::opt;
// Default hvx-length for various versions.
-static StringRef getDefaultHvxLength(StringRef Cpu) {
- return llvm::StringSwitch<StringRef>(Cpu)
+static StringRef getDefaultHvxLength(StringRef HvxVer) {
+ return llvm::StringSwitch<StringRef>(HvxVer)
.Case("v60", "64b")
.Case("v62", "64b")
.Case("v65", "64b")
@@ -40,7 +40,7 @@ static void handleHVXWarnings(const Driver &D, const ArgList &Args) {
StringRef Val = A->getValue();
if (!Val.equals_insensitive("64b") && !Val.equals_insensitive("128b"))
D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << Val;
+ << A->getSpelling() << Val;
}
}
@@ -51,49 +51,119 @@ static void handleHVXTargetFeatures(const Driver &D, const ArgList &Args,
// Handle HVX warnings.
handleHVXWarnings(D, Args);
- // Add the +hvx* features based on commandline flags.
- StringRef HVXFeature, HVXLength;
-
- // Handle -mhvx, -mhvx=, -mno-hvx.
- if (Arg *A = Args.getLastArg(options::OPT_mno_hexagon_hvx,
- options::OPT_mhexagon_hvx,
- options::OPT_mhexagon_hvx_EQ)) {
- if (A->getOption().matches(options::OPT_mno_hexagon_hvx))
- return;
- if (A->getOption().matches(options::OPT_mhexagon_hvx_EQ)) {
- HasHVX = true;
- HVXFeature = Cpu = A->getValue();
- HVXFeature = Args.MakeArgString(llvm::Twine("+hvx") + HVXFeature.lower());
- } else if (A->getOption().matches(options::OPT_mhexagon_hvx)) {
- HasHVX = true;
- HVXFeature = Args.MakeArgString(llvm::Twine("+hvx") + Cpu);
+ auto makeFeature = [&Args](Twine T, bool Enable) -> StringRef {
+ const std::string &S = T.str();
+ StringRef Opt(S);
+ if (Opt.ends_with("="))
+ Opt = Opt.drop_back(1);
+ if (Opt.starts_with("mno-"))
+ Opt = Opt.drop_front(4);
+ else if (Opt.starts_with("m"))
+ Opt = Opt.drop_front(1);
+ return Args.MakeArgString(Twine(Enable ? "+" : "-") + Twine(Opt));
+ };
+
+ auto withMinus = [](StringRef S) -> std::string {
+ return "-" + S.str();
+ };
+
+ // Drop tiny core suffix for HVX version.
+ std::string HvxVer =
+ (Cpu.back() == 'T' || Cpu.back() == 't' ? Cpu.drop_back(1) : Cpu).str();
+ HasHVX = false;
+
+ // Handle -mhvx, -mhvx=, -mno-hvx. If versioned and versionless flags
+ // are both present, the last one wins.
+ Arg *HvxEnablingArg =
+ Args.getLastArg(options::OPT_mhexagon_hvx, options::OPT_mhexagon_hvx_EQ,
+ options::OPT_mno_hexagon_hvx);
+ if (HvxEnablingArg) {
+ if (HvxEnablingArg->getOption().matches(options::OPT_mno_hexagon_hvx))
+ HvxEnablingArg = nullptr;
+ }
+
+ if (HvxEnablingArg) {
+ // If -mhvx[=] was given, it takes precedence.
+ if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx,
+ options::OPT_mhexagon_hvx_EQ)) {
+ // If the version was given, set HvxVer. Otherwise HvxVer
+ // will remain equal to the CPU version.
+ if (A->getOption().matches(options::OPT_mhexagon_hvx_EQ))
+ HvxVer = StringRef(A->getValue()).lower();
}
- Features.push_back(HVXFeature);
+ HasHVX = true;
+ Features.push_back(makeFeature(Twine("hvx") + HvxVer, true));
+ } else if (Arg *A = Args.getLastArg(options::OPT_mno_hexagon_hvx)) {
+ // If there was an explicit -mno-hvx, add -hvx to target features.
+ Features.push_back(makeFeature(A->getOption().getName(), false));
}
+ StringRef HvxLen = getDefaultHvxLength(HvxVer);
+
// Handle -mhvx-length=.
if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) {
// These flags are valid only if HVX in enabled.
if (!HasHVX)
- D.Diag(diag::err_drv_invalid_hvx_length);
+ D.Diag(diag::err_drv_needs_hvx) << withMinus(A->getOption().getName());
else if (A->getOption().matches(options::OPT_mhexagon_hvx_length_EQ))
- HVXLength = A->getValue();
+ HvxLen = A->getValue();
}
- // Default hvx-length based on Cpu.
- else if (HasHVX)
- HVXLength = getDefaultHvxLength(Cpu);
-
- if (!HVXLength.empty()) {
- HVXFeature =
- Args.MakeArgString(llvm::Twine("+hvx-length") + HVXLength.lower());
- Features.push_back(HVXFeature);
+
+ if (HasHVX) {
+ StringRef L = makeFeature(Twine("hvx-length") + HvxLen.lower(), true);
+ Features.push_back(L);
+ }
+
+ unsigned HvxVerNum;
+ // getAsInteger returns 'true' on error.
+ if (StringRef(HvxVer).drop_front(1).getAsInteger(10, HvxVerNum))
+ HvxVerNum = 0;
+
+ // Handle HVX floating point flags.
+ auto checkFlagHvxVersion =
+ [&](auto FlagOn, auto FlagOff,
+ unsigned MinVerNum) -> std::optional<StringRef> {
+ // Return an std::optional<StringRef>:
+ // - std::nullopt indicates a verification failure, or that the flag was not
+ // present in Args.
+ // - Otherwise the returned value is that name of the feature to add
+ // to Features.
+ Arg *A = Args.getLastArg(FlagOn, FlagOff);
+ if (!A)
+ return std::nullopt;
+
+ StringRef OptName = A->getOption().getName();
+ if (A->getOption().matches(FlagOff))
+ return makeFeature(OptName, false);
+
+ if (!HasHVX) {
+ D.Diag(diag::err_drv_needs_hvx) << withMinus(OptName);
+ return std::nullopt;
+ }
+ if (HvxVerNum < MinVerNum) {
+ D.Diag(diag::err_drv_needs_hvx_version)
+ << withMinus(OptName) << ("v" + std::to_string(HvxVerNum));
+ return std::nullopt;
+ }
+ return makeFeature(OptName, true);
+ };
+
+ if (auto F = checkFlagHvxVersion(options::OPT_mhexagon_hvx_qfloat,
+ options::OPT_mno_hexagon_hvx_qfloat, 68)) {
+ Features.push_back(*F);
+ }
+ if (auto F = checkFlagHvxVersion(options::OPT_mhexagon_hvx_ieee_fp,
+ options::OPT_mno_hexagon_hvx_ieee_fp, 68)) {
+ Features.push_back(*F);
}
}
// Hexagon target features.
-void hexagon::getHexagonTargetFeatures(const Driver &D, const ArgList &Args,
+void hexagon::getHexagonTargetFeatures(const Driver &D,
+ const llvm::Triple &Triple,
+ const ArgList &Args,
std::vector<StringRef> &Features) {
- handleTargetFeaturesGroup(Args, Features,
+ handleTargetFeaturesGroup(D, Triple, Args, Features,
options::OPT_m_hexagon_Features_Group);
bool UseLongCalls = false;
@@ -117,7 +187,7 @@ void hexagon::getHexagonTargetFeatures(const Driver &D, const ArgList &Args,
handleHVXTargetFeatures(D, Args, Features, Cpu, HasHVX);
if (HexagonToolChain::isAutoHVXEnabled(Args) && !HasHVX)
- D.Diag(diag::warn_drv_vectorize_needs_hvx);
+ D.Diag(diag::warn_drv_needs_hvx) << "auto-vectorization";
}
// Hexagon tools start.
@@ -146,16 +216,24 @@ void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
"-mcpu=hexagon" +
toolchains::HexagonToolChain::GetTargetCPUVersion(Args)));
+ addSanitizerRuntimes(HTC, Args, CmdArgs);
+
+ assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
} else {
- assert(Output.isNothing() && "Unexpected output");
CmdArgs.push_back("-fsyntax-only");
}
+ if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_ieee_fp,
+ options::OPT_mno_hexagon_hvx_ieee_fp)) {
+ if (A->getOption().matches(options::OPT_mhexagon_hvx_ieee_fp))
+ CmdArgs.push_back("-mhvx-ieee-fp");
+ }
+
if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
- CmdArgs.push_back(Args.MakeArgString("-gpsize=" + Twine(G.getValue())));
+ CmdArgs.push_back(Args.MakeArgString("-gpsize=" + Twine(*G)));
}
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
@@ -223,6 +301,9 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
bool UseShared = IsShared && !IsStatic;
StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args);
+ bool NeedsSanitizerDeps = addSanitizerRuntimes(HTC, Args, CmdArgs);
+ bool NeedsXRayDeps = addXRayRuntime(HTC, Args, CmdArgs);
+
//----------------------------------------------------------------------------
// Silence warnings for various options
//----------------------------------------------------------------------------
@@ -262,8 +343,8 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-pie");
if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
- CmdArgs.push_back(Args.MakeArgString("-G" + Twine(G.getValue())));
- UseG0 = G.getValue() == 0;
+ CmdArgs.push_back(Args.MakeArgString("-G" + Twine(*G)));
+ UseG0 = *G == 0;
}
CmdArgs.push_back("-o");
@@ -282,19 +363,31 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
CmdArgs.push_back(
Args.MakeArgString(StringRef("-L") + D.SysRoot + "/usr/lib"));
- Args.AddAllArgs(CmdArgs,
- {options::OPT_T_Group, options::OPT_e, options::OPT_s,
- options::OPT_t, options::OPT_u_Group});
+ Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s,
+ options::OPT_t, options::OPT_u_Group});
AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ if (NeedsSanitizerDeps) {
+ linkSanitizerRuntimeDeps(HTC, Args, CmdArgs);
+
+ CmdArgs.push_back("-lunwind");
+ }
+ if (NeedsXRayDeps)
+ linkXRayRuntimeDeps(HTC, Args, CmdArgs);
+
CmdArgs.push_back("-lclang_rt.builtins-hexagon");
- CmdArgs.push_back("-lc");
+ if (!Args.hasArg(options::OPT_nolibc))
+ CmdArgs.push_back("-lc");
}
if (D.CCCIsCXX()) {
if (HTC.ShouldLinkCXXStdlib(Args))
HTC.AddCXXStdlibLibArgs(Args, CmdArgs);
}
+ const ToolChain::path_list &LibPaths = HTC.getFilePaths();
+ for (const auto &LibPath : LibPaths)
+ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
+ Args.ClaimAllArgs(options::OPT_L);
return;
}
@@ -353,13 +446,13 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
const ToolChain::path_list &LibPaths = HTC.getFilePaths();
for (const auto &LibPath : LibPaths)
CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
+ Args.ClaimAllArgs(options::OPT_L);
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
- Args.AddAllArgs(CmdArgs,
- {options::OPT_T_Group, options::OPT_e, options::OPT_s,
- options::OPT_t, options::OPT_u_Group});
+ Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s,
+ options::OPT_t, options::OPT_u_Group});
AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
@@ -378,7 +471,8 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
if (!IsShared) {
for (StringRef Lib : OsLibs)
CmdArgs.push_back(Args.MakeArgString("-l" + Lib));
- CmdArgs.push_back("-lc");
+ if (!Args.hasArg(options::OPT_nolibc))
+ CmdArgs.push_back("-lc");
}
CmdArgs.push_back("-lgcc");
@@ -433,8 +527,8 @@ std::string HexagonToolChain::getHexagonTargetDir(
return InstalledDir;
}
-Optional<unsigned> HexagonToolChain::getSmallDataThreshold(
- const ArgList &Args) {
+std::optional<unsigned>
+HexagonToolChain::getSmallDataThreshold(const ArgList &Args) {
StringRef Gn = "";
if (Arg *A = Args.getLastArg(options::OPT_G)) {
Gn = A->getValue();
@@ -447,7 +541,16 @@ Optional<unsigned> HexagonToolChain::getSmallDataThreshold(
if (!Gn.getAsInteger(10, G))
return G;
- return None;
+ return std::nullopt;
+}
+
+std::string HexagonToolChain::getCompilerRTPath() const {
+ SmallString<128> Dir(getDriver().SysRoot);
+ llvm::sys::path::append(Dir, "usr", "lib");
+ if (!SelectedMultilibs.empty()) {
+ Dir += SelectedMultilibs.back().gccSuffix();
+ }
+ return std::string(Dir);
}
void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args,
@@ -458,8 +561,7 @@ void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args,
// -L Args
//----------------------------------------------------------------------------
for (Arg *A : Args.filtered(options::OPT_L))
- for (const char *Value : A->getValues())
- LibPaths.push_back(Value);
+ llvm::append_range(LibPaths, A->getValues());
//----------------------------------------------------------------------------
// Other standard paths
@@ -470,14 +572,14 @@ 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);
// Assume G0 with -shared.
bool HasG0 = Args.hasArg(options::OPT_shared);
if (auto G = getSmallDataThreshold(Args))
- HasG0 = G.getValue() == 0;
+ HasG0 = *G == 0;
const std::string CpuVer = GetTargetCPUVersion(Args).str();
for (auto &Dir : RootDirs) {
@@ -522,6 +624,8 @@ void HexagonToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
switch (Type) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back("-lc++abi");
CmdArgs.push_back("-lunwind");
break;
@@ -687,17 +791,17 @@ 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;
StringRef CPU = CpuArg ? CpuArg->getValue() : GetDefaultCPU();
- if (CPU.startswith("hexagon"))
+ if (CPU.starts_with("hexagon"))
return CPU.substr(sizeof("hexagon") - 1);
return CPU;
}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Hexagon.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Hexagon.h
index c32cb7f09591..e35a224dced4 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Hexagon.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Hexagon.h
@@ -20,7 +20,7 @@ namespace hexagon {
// For Hexagon, we do not need to instantiate tools for PreProcess, PreCompile
// and Compile.
// We simply use "clang -cc1" for those actions.
-class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
+class LLVM_LIBRARY_VISIBILITY Assembler final : public Tool {
public:
Assembler(const ToolChain &TC)
: Tool("hexagon::Assembler", "hexagon-as", TC) {}
@@ -35,7 +35,7 @@ public:
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
public:
Linker(const ToolChain &TC) : Tool("hexagon::Linker", "hexagon-ld", TC) {}
@@ -50,7 +50,8 @@ public:
const char *LinkingOutput) const override;
};
-void getHexagonTargetFeatures(const Driver &D, const llvm::opt::ArgList &Args,
+void getHexagonTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args,
std::vector<StringRef> &Features);
} // end namespace hexagon.
@@ -94,9 +95,6 @@ public:
llvm::opt::ArgStringList &CmdArgs) const override;
StringRef GetGCCLibAndIncVersion() const { return GCCLibAndIncVersion.Text; }
- bool IsIntegratedAssemblerDefault() const override {
- return true;
- }
std::string getHexagonTargetDir(
const std::string &InstalledDir,
@@ -104,12 +102,14 @@ 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);
+ static std::optional<unsigned>
+ getSmallDataThreshold(const llvm::opt::ArgList &Args);
};
} // end namespace toolchains
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Hurd.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Hurd.cpp
index 48b9ccadf36f..0bc114b90ffc 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Hurd.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Hurd.cpp
@@ -30,13 +30,21 @@ using tools::addPathIfExists;
std::string Hurd::getMultiarchTriple(const Driver &D,
const llvm::Triple &TargetTriple,
StringRef SysRoot) const {
- if (TargetTriple.getArch() == llvm::Triple::x86) {
+ switch (TargetTriple.getArch()) {
+ default:
+ break;
+
+ case llvm::Triple::x86:
// We use the existence of '/lib/<triple>' as a directory to detect some
// common hurd triples that don't quite match the Clang triple for both
// 32-bit and 64-bit targets. Multiarch fixes its install triples to these
// regardless of what the actual target triple is.
if (D.getVFS().exists(SysRoot + "/lib/i386-gnu"))
return "i386-gnu";
+ break;
+
+ case llvm::Triple::x86_64:
+ return "x86_64-gnu";
}
// For most architectures, just use whatever we have rather than trying to be
@@ -65,7 +73,7 @@ Hurd::Hurd(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
GCCInstallation.init(Triple, Args);
Multilibs = GCCInstallation.getMultilibs();
- SelectedMultilib = GCCInstallation.getMultilib();
+ SelectedMultilibs.assign({GCCInstallation.getMultilib()});
std::string SysRoot = computeSysRoot();
ToolChain::path_list &PPaths = getProgramPaths();
@@ -92,7 +100,7 @@ Hurd::Hurd(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// those searched.
// FIXME: It's not clear whether we should use the driver's installed
// directory ('Dir' below) or the ResourceDir.
- if (StringRef(D.Dir).startswith(SysRoot)) {
+ if (StringRef(D.Dir).starts_with(SysRoot)) {
addPathIfExists(D, D.Dir + "/../lib/" + MultiarchTriple, Paths);
addPathIfExists(D, D.Dir + "/../" + OSLibDir, Paths);
}
@@ -110,7 +118,7 @@ Hurd::Hurd(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).starts_with(SysRoot))
addPathIfExists(D, D.Dir + "/../lib", Paths);
addPathIfExists(D, SysRoot + "/lib", Paths);
@@ -126,8 +134,14 @@ Tool *Hurd::buildAssembler() const {
}
std::string Hurd::getDynamicLinker(const ArgList &Args) const {
- if (getArch() == llvm::Triple::x86)
+ switch (getArch()) {
+ case llvm::Triple::x86:
return "/lib/ld.so";
+ case llvm::Triple::x86_64:
+ return "/lib/ld-x86-64.so.1";
+ default:
+ break;
+ }
llvm_unreachable("unsupported architecture");
}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Lanai.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Lanai.h
index dc04b0cfe2ee..33701f7cc045 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Lanai.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Lanai.h
@@ -29,8 +29,6 @@ public:
void addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override {}
-
- bool IsIntegratedAssemblerDefault() const override { return true; }
};
} // end namespace toolchains
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/LazyDetector.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/LazyDetector.h
new file mode 100644
index 000000000000..813d00a87bb8
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/LazyDetector.h
@@ -0,0 +1,45 @@
+//===--- LazyDetector.h - Lazy ToolChain Detection --------------*- 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_LAZYDETECTOR_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_LAZYDETECTOR_H
+
+#include "clang/Driver/Tool.h"
+#include "clang/Driver/ToolChain.h"
+#include <optional>
+
+namespace clang {
+
+/// Simple wrapper for toolchain detector with costly initialization. This
+/// delays the creation of the actual detector until its first usage.
+
+template <class T> class LazyDetector {
+ const driver::Driver &D;
+ llvm::Triple Triple;
+ const llvm::opt::ArgList &Args;
+
+ std::optional<T> Detector;
+
+public:
+ LazyDetector(const driver::Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args)
+ : D(D), Triple(Triple), Args(Args) {}
+ T *operator->() {
+ if (!Detector)
+ Detector.emplace(D, Triple, Args);
+ return &*Detector;
+ }
+ const T *operator->() const {
+ return const_cast<T const *>(
+ const_cast<LazyDetector &>(*this).operator->());
+ }
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_LAZYDETECTOR_H
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Linux.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Linux.cpp
index c9360fc67165..4300a2bdff17 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Linux.cpp
@@ -8,6 +8,7 @@
#include "Linux.h"
#include "Arch/ARM.h"
+#include "Arch/LoongArch.h"
#include "Arch/Mips.h"
#include "Arch/PPC.h"
#include "Arch/RISCV.h"
@@ -60,12 +61,16 @@ std::string Linux::getMultiarchTriple(const Driver &D,
case llvm::Triple::thumb:
if (IsAndroid)
return "arm-linux-androideabi";
- if (TargetEnvironment == llvm::Triple::GNUEABIHF)
+ if (TargetEnvironment == llvm::Triple::GNUEABIHF ||
+ TargetEnvironment == llvm::Triple::MuslEABIHF ||
+ TargetEnvironment == llvm::Triple::EABIHF)
return "arm-linux-gnueabihf";
return "arm-linux-gnueabi";
case llvm::Triple::armeb:
case llvm::Triple::thumbeb:
- if (TargetEnvironment == llvm::Triple::GNUEABIHF)
+ if (TargetEnvironment == llvm::Triple::GNUEABIHF ||
+ TargetEnvironment == llvm::Triple::MuslEABIHF ||
+ TargetEnvironment == llvm::Triple::EABIHF)
return "armeb-linux-gnueabihf";
return "armeb-linux-gnueabi";
case llvm::Triple::x86:
@@ -85,37 +90,66 @@ std::string Linux::getMultiarchTriple(const Driver &D,
case llvm::Triple::aarch64_be:
return "aarch64_be-linux-gnu";
+ case llvm::Triple::loongarch64: {
+ const char *Libc;
+ const char *FPFlavor;
+
+ if (TargetTriple.isGNUEnvironment()) {
+ Libc = "gnu";
+ } else if (TargetTriple.isMusl()) {
+ Libc = "musl";
+ } else {
+ return TargetTriple.str();
+ }
+
+ switch (TargetEnvironment) {
+ default:
+ return TargetTriple.str();
+ case llvm::Triple::GNUSF:
+ FPFlavor = "sf";
+ break;
+ case llvm::Triple::GNUF32:
+ FPFlavor = "f32";
+ break;
+ case llvm::Triple::GNU:
+ case llvm::Triple::GNUF64:
+ // This was going to be "f64" in an earlier Toolchain Conventions
+ // revision, but starting from Feb 2023 the F64 ABI variants are
+ // unmarked in their canonical forms.
+ FPFlavor = "";
+ break;
+ }
+
+ return (Twine("loongarch64-linux-") + Libc + FPFlavor).str();
+ }
+
case llvm::Triple::m68k:
return "m68k-linux-gnu";
case llvm::Triple::mips:
return IsMipsR6 ? "mipsisa32r6-linux-gnu" : "mips-linux-gnu";
case llvm::Triple::mipsel:
- if (IsAndroid)
- return "mipsel-linux-android";
return IsMipsR6 ? "mipsisa32r6el-linux-gnu" : "mipsel-linux-gnu";
case llvm::Triple::mips64: {
std::string MT = std::string(IsMipsR6 ? "mipsisa64r6" : "mips64") +
"-linux-" + (IsMipsN32Abi ? "gnuabin32" : "gnuabi64");
- if (D.getVFS().exists(SysRoot + "/lib/" + MT))
+ if (D.getVFS().exists(concat(SysRoot, "/lib", MT)))
return MT;
- if (D.getVFS().exists(SysRoot + "/lib/mips64-linux-gnu"))
+ if (D.getVFS().exists(concat(SysRoot, "/lib/mips64-linux-gnu")))
return "mips64-linux-gnu";
break;
}
case llvm::Triple::mips64el: {
- if (IsAndroid)
- return "mips64el-linux-android";
std::string MT = std::string(IsMipsR6 ? "mipsisa64r6el" : "mips64el") +
"-linux-" + (IsMipsN32Abi ? "gnuabin32" : "gnuabi64");
- if (D.getVFS().exists(SysRoot + "/lib/" + MT))
+ if (D.getVFS().exists(concat(SysRoot, "/lib", MT)))
return MT;
- if (D.getVFS().exists(SysRoot + "/lib/mips64el-linux-gnu"))
+ if (D.getVFS().exists(concat(SysRoot, "/lib/mips64el-linux-gnu")))
return "mips64el-linux-gnu";
break;
}
case llvm::Triple::ppc:
- if (D.getVFS().exists(SysRoot + "/lib/powerpc-linux-gnuspe"))
+ if (D.getVFS().exists(concat(SysRoot, "/lib/powerpc-linux-gnuspe")))
return "powerpc-linux-gnuspe";
return "powerpc-linux-gnu";
case llvm::Triple::ppcle:
@@ -124,6 +158,10 @@ std::string Linux::getMultiarchTriple(const Driver &D,
return "powerpc64-linux-gnu";
case llvm::Triple::ppc64le:
return "powerpc64le-linux-gnu";
+ case llvm::Triple::riscv64:
+ if (IsAndroid)
+ return "riscv64-linux-android";
+ return "riscv64-linux-gnu";
case llvm::Triple::sparc:
return "sparc-linux-gnu";
case llvm::Triple::sparcv9:
@@ -179,7 +217,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
GCCInstallation.init(Triple, Args);
Multilibs = GCCInstallation.getMultilibs();
- SelectedMultilib = GCCInstallation.getMultilib();
+ SelectedMultilibs.assign({GCCInstallation.getMultilib()});
llvm::Triple::ArchType Arch = Triple.getArch();
std::string SysRoot = computeSysRoot();
ToolChain::path_list &PPaths = getProgramPaths();
@@ -206,8 +244,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
@@ -222,8 +259,12 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
const bool IsMips = Triple.isMIPS();
const bool IsHexagon = Arch == llvm::Triple::hexagon;
const bool IsRISCV = Triple.isRISCV();
+ const bool IsCSKY = Triple.isCSKY();
- if (IsMips && !SysRoot.empty())
+ if (IsCSKY && !SelectedMultilibs.empty())
+ SysRoot = SysRoot + SelectedMultilibs.back().osSuffix();
+
+ if ((IsMips || IsCSKY) && !SysRoot.empty())
ExtraOpts.push_back("--sysroot=" + SysRoot);
// Do not use 'gnu' hash style for Mips targets because .gnu.hash
@@ -233,25 +274,18 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// Android loader does not support .gnu.hash until API 23.
// Hexagon linker/loader does not support .gnu.hash
if (!IsMips && !IsHexagon) {
- if (Distro.IsRedhat() || Distro.IsOpenSUSE() || Distro.IsAlpineLinux() ||
- (Distro.IsUbuntu() && Distro >= Distro::UbuntuMaverick) ||
- (IsAndroid && !Triple.isAndroidVersionLT(23)))
- ExtraOpts.push_back("--hash-style=gnu");
-
- if (Distro.IsDebian() || Distro.IsOpenSUSE() ||
- Distro == Distro::UbuntuLucid || Distro == Distro::UbuntuJaunty ||
- Distro == Distro::UbuntuKarmic ||
+ if (Distro.IsOpenSUSE() || Distro == Distro::UbuntuLucid ||
+ Distro == Distro::UbuntuJaunty || Distro == Distro::UbuntuKarmic ||
(IsAndroid && Triple.isAndroidVersionLT(23)))
ExtraOpts.push_back("--hash-style=both");
+ else
+ ExtraOpts.push_back("--hash-style=gnu");
}
#ifdef ENABLE_LINKER_BUILD_ID
ExtraOpts.push_back("--build-id");
#endif
- if (IsAndroid || Distro.IsOpenSUSE())
- ExtraOpts.push_back("--enable-new-dtags");
-
// The selection of paths to try here is designed to match the patterns which
// the GCC driver itself uses, as this is part of the GCC-compatible driver.
// This was determined by running GCC in a fake filesystem, creating all
@@ -262,52 +296,48 @@ 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, concat(SysRoot, "/libo32"), Paths);
+ addPathIfExists(D, concat(SysRoot, "/usr/libo32"), Paths);
+ }
Generic_GCC::AddMultilibPaths(D, SysRoot, OSLibDir, MultiarchTriple, Paths);
- addPathIfExists(D, SysRoot + "/lib/" + MultiarchTriple, Paths);
- addPathIfExists(D, SysRoot + "/lib/../" + OSLibDir, Paths);
+ addPathIfExists(D, concat(SysRoot, "/lib", MultiarchTriple), Paths);
+ addPathIfExists(D, concat(SysRoot, "/lib/..", OSLibDir), Paths);
if (IsAndroid) {
// Android sysroots contain a library directory for each supported OS
// version as well as some unversioned libraries in the usual multiarch
// directory.
- unsigned Major;
- unsigned Minor;
- unsigned Micro;
- Triple.getEnvironmentVersion(Major, Minor, Micro);
- addPathIfExists(D,
- SysRoot + "/usr/lib/" + MultiarchTriple + "/" +
- llvm::to_string(Major),
- Paths);
+ addPathIfExists(
+ D,
+ concat(SysRoot, "/usr/lib", MultiarchTriple,
+ llvm::to_string(Triple.getEnvironmentVersion().getMajor())),
+ Paths);
}
- addPathIfExists(D, SysRoot + "/usr/lib/" + MultiarchTriple, Paths);
+ addPathIfExists(D, concat(SysRoot, "/usr/lib", MultiarchTriple), Paths);
// 64-bit OpenEmbedded sysroots may not have a /usr/lib dir. So they cannot
// find /usr/lib64 as it is referenced as /usr/lib/../lib64. So we handle
// this here.
if (Triple.getVendor() == llvm::Triple::OpenEmbedded &&
Triple.isArch64Bit())
- addPathIfExists(D, SysRoot + "/usr/" + OSLibDir, Paths);
+ addPathIfExists(D, concat(SysRoot, "/usr", OSLibDir), Paths);
else
- addPathIfExists(D, SysRoot + "/usr/lib/../" + OSLibDir, Paths);
+ addPathIfExists(D, concat(SysRoot, "/usr/lib/..", OSLibDir), Paths);
if (IsRISCV) {
StringRef ABIName = tools::riscv::getRISCVABI(Args, Triple);
- addPathIfExists(D, SysRoot + "/" + OSLibDir + "/" + ABIName, Paths);
- addPathIfExists(D, SysRoot + "/usr/" + OSLibDir + "/" + ABIName, Paths);
+ addPathIfExists(D, concat(SysRoot, "/", OSLibDir, ABIName), Paths);
+ addPathIfExists(D, concat(SysRoot, "/usr", OSLibDir, ABIName), Paths);
}
Generic_GCC::AddMultiarchPaths(D, SysRoot, OSLibDir, Paths);
- // Similar to the logic for GCC above, if we are currently running Clang
- // inside of the requested system root, add its parent library path to those
- // searched.
- // FIXME: It's not clear whether we should use the driver's installed
- // directory ('Dir' below) or the ResourceDir.
- if (StringRef(D.Dir).startswith(SysRoot))
- addPathIfExists(D, D.Dir + "/../lib", Paths);
-
- addPathIfExists(D, SysRoot + "/lib", Paths);
- addPathIfExists(D, SysRoot + "/usr/lib", Paths);
+ addPathIfExists(D, concat(SysRoot, "/lib"), Paths);
+ addPathIfExists(D, concat(SysRoot, "/usr/lib"), Paths);
}
ToolChain::RuntimeLibType Linux::GetDefaultRuntimeLibType() const {
@@ -316,6 +346,12 @@ ToolChain::RuntimeLibType Linux::GetDefaultRuntimeLibType() const {
return Generic_ELF::GetDefaultRuntimeLibType();
}
+unsigned Linux::GetDefaultDwarfVersion() const {
+ if (getTriple().isAndroid())
+ return 4;
+ return ToolChain::GetDefaultDwarfVersion();
+}
+
ToolChain::CXXStdlibType Linux::GetDefaultCXXStdlibType() const {
if (getTriple().isAndroid())
return ToolChain::CST_Libcxx;
@@ -347,6 +383,21 @@ std::string Linux::computeSysRoot() const {
return AndroidSysRootPath;
}
+ if (getTriple().isCSKY()) {
+ // CSKY toolchains use different names for sysroot folder.
+ if (!GCCInstallation.isValid())
+ return std::string();
+ // GCCInstallation.getInstallPath() =
+ // $GCCToolchainPath/lib/gcc/csky-linux-gnuabiv2/6.3.0
+ // Path = $GCCToolchainPath/csky-linux-gnuabiv2/libc
+ std::string Path = (GCCInstallation.getInstallPath() + "/../../../../" +
+ GCCInstallation.getTriple().str() + "/libc")
+ .str();
+ if (getVFS().exists(Path))
+ return Path;
+ return std::string();
+ }
+
if (!GCCInstallation.isValid() || !getTriple().isMIPS())
return std::string();
@@ -379,9 +430,17 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
const Distro Distro(getDriver().getVFS(), Triple);
- if (Triple.isAndroid())
+ if (Triple.isAndroid()) {
+ if (getSanitizerArgs(Args).needsHwasanRt() &&
+ !Triple.isAndroidVersionLT(34) && Triple.isArch64Bit()) {
+ // On Android 14 and newer, there is a special linker_hwasan64 that
+ // allows to run HWASan binaries on non-HWASan system images. This
+ // is also available on HWASan system images, so we can just always
+ // use that instead.
+ return "/system/bin/linker_hwasan64";
+ }
return Triple.isArch64Bit() ? "/system/bin/linker64" : "/system/bin/linker";
-
+ }
if (Triple.isMusl()) {
std::string ArchName;
bool IsArm = false;
@@ -410,6 +469,9 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
(Triple.getEnvironment() == llvm::Triple::MuslEABIHF ||
tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard))
ArchName += "hf";
+ if (Arch == llvm::Triple::ppc &&
+ Triple.getSubArch() == llvm::Triple::PPCSubArch_spe)
+ ArchName = "powerpc-sf";
return "/lib/ld-musl-" + ArchName + ".so.1";
}
@@ -441,6 +503,22 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
Loader = HF ? "ld-linux-armhf.so.3" : "ld-linux.so.3";
break;
}
+ case llvm::Triple::loongarch32: {
+ LibDir = "lib32";
+ Loader =
+ ("ld-linux-loongarch-" +
+ tools::loongarch::getLoongArchABI(getDriver(), Args, Triple) + ".so.1")
+ .str();
+ break;
+ }
+ case llvm::Triple::loongarch64: {
+ LibDir = "lib64";
+ Loader =
+ ("ld-linux-loongarch-" +
+ tools::loongarch::getLoongArchABI(getDriver(), Args, Triple) + ".so.1")
+ .str();
+ break;
+ }
case llvm::Triple::m68k:
LibDir = "lib";
Loader = "ld.so.1";
@@ -449,7 +527,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);
@@ -520,6 +598,11 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
}
case llvm::Triple::ve:
return "/opt/nec/ve/lib/ld-linux-ve.so.1";
+ case llvm::Triple::csky: {
+ LibDir = "lib";
+ Loader = "ld.so.1";
+ break;
+ }
}
if (Distro == Distro::Exherbo &&
@@ -551,7 +634,7 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
return;
// LOCAL_INCLUDE_DIR
- addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include");
+ addSystemInclude(DriverArgs, CC1Args, concat(SysRoot, "/usr/local/include"));
// TOOL_INCLUDE_DIR
AddMultilibIncludeArgs(DriverArgs, CC1Args);
@@ -572,9 +655,10 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
// /usr/include.
std::string MultiarchIncludeDir = getMultiarchTriple(D, getTriple(), SysRoot);
if (!MultiarchIncludeDir.empty() &&
- D.getVFS().exists(SysRoot + "/usr/include/" + MultiarchIncludeDir))
- addExternCSystemInclude(DriverArgs, CC1Args,
- SysRoot + "/usr/include/" + MultiarchIncludeDir);
+ D.getVFS().exists(concat(SysRoot, "/usr/include", MultiarchIncludeDir)))
+ addExternCSystemInclude(
+ DriverArgs, CC1Args,
+ concat(SysRoot, "/usr/include", MultiarchIncludeDir));
if (getTriple().getOS() == llvm::Triple::RTEMS)
return;
@@ -582,9 +666,9 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
// Add an include of '/include' directly. This isn't provided by default by
// system GCCs, but is often used with cross-compiling GCCs, and harmless to
// add even when Clang is acting as-if it were a system compiler.
- addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include");
+ addExternCSystemInclude(DriverArgs, CC1Args, concat(SysRoot, "/include"));
- addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
+ addExternCSystemInclude(DriverArgs, CC1Args, concat(SysRoot, "/usr/include"));
if (!DriverArgs.hasArg(options::OPT_nobuiltininc) && getTriple().isMusl())
addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);
@@ -633,12 +717,25 @@ void Linux::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
void Linux::AddCudaIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
- CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
+ CudaInstallation->AddCudaIncludeArgs(DriverArgs, CC1Args);
}
void Linux::AddHIPIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
- RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
+ RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args);
+}
+
+void Linux::AddHIPRuntimeLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ CmdArgs.push_back(
+ Args.MakeArgString(StringRef("-L") + RocmInstallation->getLibPath()));
+
+ if (Args.hasFlag(options::OPT_frtlib_add_rpath,
+ options::OPT_fno_rtlib_add_rpath, false))
+ CmdArgs.append(
+ {"-rpath", Args.MakeArgString(RocmInstallation->getLibPath())});
+
+ CmdArgs.push_back("-lamdhip64");
}
void Linux::AddIAMCUIncludeArgs(const ArgList &DriverArgs,
@@ -651,9 +748,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 CLANG_DEFAULT_PIE_ON_LINUX || getTriple().isAndroid() ||
+ getTriple().isMusl() || getSanitizerArgs(Args).requiresPIE();
}
bool Linux::IsAArch64OutlineAtomicsDefault(const ArgList &Args) const {
@@ -669,12 +766,8 @@ bool Linux::IsAArch64OutlineAtomicsDefault(const ArgList &Args) const {
return true;
}
-bool Linux::isNoExecStackDefault() const {
- return getTriple().isAndroid();
-}
-
bool Linux::IsMathErrnoDefault() const {
- if (getTriple().isAndroid())
+ if (getTriple().isAndroid() || getTriple().isMusl())
return false;
return Generic_ELF::IsMathErrnoDefault();
}
@@ -692,8 +785,10 @@ SanitizerMask Linux::getSupportedSanitizers() const {
getTriple().getArch() == llvm::Triple::thumb ||
getTriple().getArch() == llvm::Triple::armeb ||
getTriple().getArch() == llvm::Triple::thumbeb;
+ const bool IsLoongArch64 = getTriple().getArch() == llvm::Triple::loongarch64;
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;
@@ -704,24 +799,28 @@ SanitizerMask Linux::getSupportedSanitizers() const {
Res |= SanitizerKind::Memory;
Res |= SanitizerKind::Vptr;
Res |= SanitizerKind::SafeStack;
- if (IsX86_64 || IsMIPS64 || IsAArch64)
+ if (IsX86_64 || IsMIPS64 || IsAArch64 || IsLoongArch64)
Res |= SanitizerKind::DataFlow;
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsArmArch || IsPowerPC64 ||
- IsRISCV64 || IsSystemZ)
+ IsRISCV64 || IsSystemZ || IsHexagon || IsLoongArch64)
Res |= SanitizerKind::Leak;
- if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64 || IsSystemZ)
+ if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64 || IsSystemZ ||
+ IsLoongArch64 || IsRISCV64)
Res |= SanitizerKind::Thread;
- if (IsX86_64)
+ if (IsX86_64 || IsSystemZ)
Res |= SanitizerKind::KernelMemory;
- if (IsX86 || IsX86_64)
- Res |= SanitizerKind::Function;
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsMIPS || IsArmArch ||
- IsPowerPC64)
+ IsPowerPC64 || IsHexagon || IsLoongArch64 || IsRISCV64)
Res |= SanitizerKind::Scudo;
- if (IsX86_64 || IsAArch64) {
+ if (IsX86_64 || IsAArch64 || IsRISCV64) {
Res |= SanitizerKind::HWAddress;
+ }
+ if (IsX86_64 || IsAArch64) {
Res |= SanitizerKind::KernelHWAddress;
}
+ // Work around "Cannot represent a difference across sections".
+ if (getTriple().getArch() == llvm::Triple::ppc64)
+ Res &= ~SanitizerKind::Function;
return Res;
}
@@ -758,3 +857,9 @@ void Linux::addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const {
for (const auto &Opt : ExtraOpts)
CmdArgs.push_back(Opt.c_str());
}
+
+const char *Linux::getDefaultLinker() const {
+ if (getTriple().isAndroid())
+ return "ld.lld";
+ return Generic_ELF::getDefaultLinker();
+}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Linux.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Linux.h
index 169a37c44072..524391743090 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Linux.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Linux.h
@@ -37,14 +37,16 @@ public:
llvm::opt::ArgStringList &CC1Args) const override;
void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+ void AddHIPRuntimeLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
RuntimeLibType GetDefaultRuntimeLibType() const override;
+ unsigned GetDefaultDwarfVersion() const override;
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,
@@ -61,6 +63,8 @@ public:
const llvm::opt::ArgList &DriverArgs, const JobAction &JA,
const llvm::fltSemantics *FPType = nullptr) const override;
+ const char *getDefaultLinker() const override;
+
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/MSP430.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/MSP430.cpp
index 96994ba77fac..07e875c64960 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/MSP430.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/MSP430.cpp
@@ -101,7 +101,7 @@ void msp430::getMSP430TargetFeatures(const Driver &D, const ArgList &Args,
Features.push_back("+hwmultf5");
} else {
D.Diag(clang::diag::err_drv_unsupported_option_argument)
- << HWMultArg->getAsString(Args) << HWMult;
+ << HWMultArg->getSpelling() << HWMult;
}
}
@@ -142,7 +142,7 @@ std::string MSP430ToolChain::computeSysRoot() const {
else
llvm::sys::path::append(Dir, getDriver().Dir, "..");
- return std::string(Dir.str());
+ return std::string(Dir);
}
void MSP430ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
@@ -166,7 +166,7 @@ void MSP430ToolChain::addClangTargetOptions(const ArgList &DriverArgs,
return;
const StringRef MCU = MCUArg->getValue();
- if (MCU.startswith("msp430i")) {
+ if (MCU.starts_with("msp430i")) {
// 'i' should be in lower case as it's defined in TI MSP430-GCC headers
CC1Args.push_back(DriverArgs.MakeArgString(
"-D__MSP430i" + MCU.drop_front(7).upper() + "__"));
@@ -279,8 +279,7 @@ void msp430::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_r, options::OPT_g_Group))
CmdArgs.push_back("--gc-sections");
- Args.AddAllArgs(CmdArgs, {
- options::OPT_e,
+ Args.addAllArgs(CmdArgs, {
options::OPT_n,
options::OPT_s,
options::OPT_t,
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/MSP430.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/MSP430.h
index 9d247ca3a896..a224c6375411 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/MSP430.h
+++ b/contrib/llvm-project/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
@@ -57,7 +59,7 @@ private:
namespace tools {
namespace msp430 {
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
public:
Linker(const ToolChain &TC) : Tool("MSP430::Linker", "msp430-elf-ld", TC) {}
bool hasIntegratedCPP() const override { return false; }
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/MSVC.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/MSVC.cpp
index 0dc94a4c6c7d..396522225158 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -18,17 +18,16 @@
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/TargetParser/Host.h"
#include <cstdio>
#ifdef _WIN32
@@ -40,23 +39,6 @@
#include <windows.h>
#endif
-#ifdef _MSC_VER
-// Don't support SetupApi on MinGW.
-#define USE_MSVC_SETUP_API
-
-// Make sure this comes before MSVCSetupApi.h
-#include <comdef.h>
-
-#include "MSVCSetupApi.h"
-#include "llvm/Support/COM.h"
-_COM_SMARTPTR_TYPEDEF(ISetupConfiguration, __uuidof(ISetupConfiguration));
-_COM_SMARTPTR_TYPEDEF(ISetupConfiguration2, __uuidof(ISetupConfiguration2));
-_COM_SMARTPTR_TYPEDEF(ISetupHelper, __uuidof(ISetupHelper));
-_COM_SMARTPTR_TYPEDEF(IEnumSetupInstances, __uuidof(IEnumSetupInstances));
-_COM_SMARTPTR_TYPEDEF(ISetupInstance, __uuidof(ISetupInstance));
-_COM_SMARTPTR_TYPEDEF(ISetupInstance2, __uuidof(ISetupInstance2));
-#endif
-
using namespace clang::driver;
using namespace clang::driver::toolchains;
using namespace clang::driver::tools;
@@ -70,294 +52,6 @@ static bool canExecute(llvm::vfs::FileSystem &VFS, StringRef Path) {
return (Status->getPermissions() & llvm::sys::fs::perms::all_exe) != 0;
}
-// Defined below.
-// Forward declare this so there aren't too many things above the constructor.
-static bool getSystemRegistryString(const char *keyPath, const char *valueName,
- std::string &value, std::string *phValue);
-
-static std::string getHighestNumericTupleInDirectory(llvm::vfs::FileSystem &VFS,
- StringRef Directory) {
- std::string Highest;
- llvm::VersionTuple HighestTuple;
-
- std::error_code EC;
- for (llvm::vfs::directory_iterator DirIt = VFS.dir_begin(Directory, EC),
- DirEnd;
- !EC && DirIt != DirEnd; DirIt.increment(EC)) {
- auto Status = VFS.status(DirIt->path());
- if (!Status || !Status->isDirectory())
- continue;
- StringRef CandidateName = llvm::sys::path::filename(DirIt->path());
- llvm::VersionTuple Tuple;
- if (Tuple.tryParse(CandidateName)) // tryParse() returns true on error.
- continue;
- if (Tuple > HighestTuple) {
- HighestTuple = Tuple;
- Highest = CandidateName.str();
- }
- }
-
- return Highest;
-}
-
-// Check command line arguments to try and find a toolchain.
-static bool
-findVCToolChainViaCommandLine(llvm::vfs::FileSystem &VFS, const ArgList &Args,
- std::string &Path,
- MSVCToolChain::ToolsetLayout &VSLayout) {
- // Don't validate the input; trust the value supplied by the user.
- // The primary motivation is to prevent unnecessary file and registry access.
- if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir,
- options::OPT__SLASH_winsysroot)) {
- if (A->getOption().getID() == options::OPT__SLASH_winsysroot) {
- llvm::SmallString<128> ToolsPath(A->getValue());
- llvm::sys::path::append(ToolsPath, "VC", "Tools", "MSVC");
- std::string VCToolsVersion;
- if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsversion))
- VCToolsVersion = A->getValue();
- else
- VCToolsVersion = getHighestNumericTupleInDirectory(VFS, ToolsPath);
- llvm::sys::path::append(ToolsPath, VCToolsVersion);
- Path = std::string(ToolsPath.str());
- } else {
- Path = A->getValue();
- }
- VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
- return true;
- }
- return false;
-}
-
-// Check various environment variables to try and find a toolchain.
-static bool
-findVCToolChainViaEnvironment(llvm::vfs::FileSystem &VFS, std::string &Path,
- MSVCToolChain::ToolsetLayout &VSLayout) {
- // These variables are typically set by vcvarsall.bat
- // when launching a developer command prompt.
- if (llvm::Optional<std::string> VCToolsInstallDir =
- llvm::sys::Process::GetEnv("VCToolsInstallDir")) {
- // This is only set by newer Visual Studios, and it leads straight to
- // the toolchain directory.
- Path = std::move(*VCToolsInstallDir);
- VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
- return true;
- }
- if (llvm::Optional<std::string> VCInstallDir =
- llvm::sys::Process::GetEnv("VCINSTALLDIR")) {
- // If the previous variable isn't set but this one is, then we've found
- // an older Visual Studio. This variable is set by newer Visual Studios too,
- // so this check has to appear second.
- // In older Visual Studios, the VC directory is the toolchain.
- Path = std::move(*VCInstallDir);
- VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
- return true;
- }
-
- // We couldn't find any VC environment variables. Let's walk through PATH and
- // see if it leads us to a VC toolchain bin directory. If it does, pick the
- // first one that we find.
- if (llvm::Optional<std::string> PathEnv =
- llvm::sys::Process::GetEnv("PATH")) {
- llvm::SmallVector<llvm::StringRef, 8> PathEntries;
- llvm::StringRef(*PathEnv).split(PathEntries, llvm::sys::EnvPathSeparator);
- for (llvm::StringRef PathEntry : PathEntries) {
- if (PathEntry.empty())
- continue;
-
- llvm::SmallString<256> ExeTestPath;
-
- // If cl.exe doesn't exist, then this definitely isn't a VC toolchain.
- ExeTestPath = PathEntry;
- llvm::sys::path::append(ExeTestPath, "cl.exe");
- if (!VFS.exists(ExeTestPath))
- continue;
-
- // cl.exe existing isn't a conclusive test for a VC toolchain; clang also
- // has a cl.exe. So let's check for link.exe too.
- ExeTestPath = PathEntry;
- llvm::sys::path::append(ExeTestPath, "link.exe");
- if (!VFS.exists(ExeTestPath))
- continue;
-
- // whatever/VC/bin --> old toolchain, VC dir is toolchain dir.
- llvm::StringRef TestPath = PathEntry;
- bool IsBin =
- llvm::sys::path::filename(TestPath).equals_insensitive("bin");
- if (!IsBin) {
- // Strip any architecture subdir like "amd64".
- TestPath = llvm::sys::path::parent_path(TestPath);
- IsBin = llvm::sys::path::filename(TestPath).equals_insensitive("bin");
- }
- if (IsBin) {
- llvm::StringRef ParentPath = llvm::sys::path::parent_path(TestPath);
- llvm::StringRef ParentFilename = llvm::sys::path::filename(ParentPath);
- if (ParentFilename.equals_insensitive("VC")) {
- Path = std::string(ParentPath);
- VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
- return true;
- }
- if (ParentFilename.equals_insensitive("x86ret") ||
- ParentFilename.equals_insensitive("x86chk") ||
- ParentFilename.equals_insensitive("amd64ret") ||
- ParentFilename.equals_insensitive("amd64chk")) {
- Path = std::string(ParentPath);
- VSLayout = MSVCToolChain::ToolsetLayout::DevDivInternal;
- return true;
- }
-
- } else {
- // This could be a new (>=VS2017) toolchain. If it is, we should find
- // path components with these prefixes when walking backwards through
- // the path.
- // Note: empty strings match anything.
- llvm::StringRef ExpectedPrefixes[] = {"", "Host", "bin", "",
- "MSVC", "Tools", "VC"};
-
- auto It = llvm::sys::path::rbegin(PathEntry);
- auto End = llvm::sys::path::rend(PathEntry);
- for (llvm::StringRef Prefix : ExpectedPrefixes) {
- if (It == End)
- goto NotAToolChain;
- if (!It->startswith_insensitive(Prefix))
- goto NotAToolChain;
- ++It;
- }
-
- // We've found a new toolchain!
- // Back up 3 times (/bin/Host/arch) to get the root path.
- llvm::StringRef ToolChainPath(PathEntry);
- for (int i = 0; i < 3; ++i)
- ToolChainPath = llvm::sys::path::parent_path(ToolChainPath);
-
- Path = std::string(ToolChainPath);
- VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
- return true;
- }
-
- NotAToolChain:
- continue;
- }
- }
- return false;
-}
-
-// Query the Setup Config server for installs, then pick the newest version
-// and find its default VC toolchain.
-// This is the preferred way to discover new Visual Studios, as they're no
-// longer listed in the registry.
-static bool
-findVCToolChainViaSetupConfig(llvm::vfs::FileSystem &VFS, std::string &Path,
- MSVCToolChain::ToolsetLayout &VSLayout) {
-#if !defined(USE_MSVC_SETUP_API)
- return false;
-#else
- // FIXME: This really should be done once in the top-level program's main
- // function, as it may have already been initialized with a different
- // threading model otherwise.
- llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::SingleThreaded);
- HRESULT HR;
-
- // _com_ptr_t will throw a _com_error if a COM calls fail.
- // The LLVM coding standards forbid exception handling, so we'll have to
- // stop them from being thrown in the first place.
- // The destructor will put the regular error handler back when we leave
- // this scope.
- struct SuppressCOMErrorsRAII {
- static void __stdcall handler(HRESULT hr, IErrorInfo *perrinfo) {}
-
- SuppressCOMErrorsRAII() { _set_com_error_handler(handler); }
-
- ~SuppressCOMErrorsRAII() { _set_com_error_handler(_com_raise_error); }
-
- } COMErrorSuppressor;
-
- ISetupConfigurationPtr Query;
- HR = Query.CreateInstance(__uuidof(SetupConfiguration));
- if (FAILED(HR))
- return false;
-
- IEnumSetupInstancesPtr EnumInstances;
- HR = ISetupConfiguration2Ptr(Query)->EnumAllInstances(&EnumInstances);
- if (FAILED(HR))
- return false;
-
- ISetupInstancePtr Instance;
- HR = EnumInstances->Next(1, &Instance, nullptr);
- if (HR != S_OK)
- return false;
-
- ISetupInstancePtr NewestInstance;
- Optional<uint64_t> NewestVersionNum;
- do {
- bstr_t VersionString;
- uint64_t VersionNum;
- HR = Instance->GetInstallationVersion(VersionString.GetAddress());
- if (FAILED(HR))
- continue;
- HR = ISetupHelperPtr(Query)->ParseVersion(VersionString, &VersionNum);
- if (FAILED(HR))
- continue;
- if (!NewestVersionNum || (VersionNum > NewestVersionNum)) {
- NewestInstance = Instance;
- NewestVersionNum = VersionNum;
- }
- } while ((HR = EnumInstances->Next(1, &Instance, nullptr)) == S_OK);
-
- if (!NewestInstance)
- return false;
-
- bstr_t VCPathWide;
- HR = NewestInstance->ResolvePath(L"VC", VCPathWide.GetAddress());
- if (FAILED(HR))
- return false;
-
- std::string VCRootPath;
- llvm::convertWideToUTF8(std::wstring(VCPathWide), VCRootPath);
-
- llvm::SmallString<256> ToolsVersionFilePath(VCRootPath);
- llvm::sys::path::append(ToolsVersionFilePath, "Auxiliary", "Build",
- "Microsoft.VCToolsVersion.default.txt");
-
- auto ToolsVersionFile = llvm::MemoryBuffer::getFile(ToolsVersionFilePath);
- if (!ToolsVersionFile)
- return false;
-
- llvm::SmallString<256> ToolchainPath(VCRootPath);
- llvm::sys::path::append(ToolchainPath, "Tools", "MSVC",
- ToolsVersionFile->get()->getBuffer().rtrim());
- auto Status = VFS.status(ToolchainPath);
- if (!Status || !Status->isDirectory())
- return false;
-
- Path = std::string(ToolchainPath.str());
- VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
- return true;
-#endif
-}
-
-// Look in the registry for Visual Studio installs, and use that to get
-// a toolchain path. VS2017 and newer don't get added to the registry.
-// So if we find something here, we know that it's an older version.
-static bool findVCToolChainViaRegistry(std::string &Path,
- MSVCToolChain::ToolsetLayout &VSLayout) {
- std::string VSInstallPath;
- if (getSystemRegistryString(R"(SOFTWARE\Microsoft\VisualStudio\$VERSION)",
- "InstallDir", VSInstallPath, nullptr) ||
- getSystemRegistryString(R"(SOFTWARE\Microsoft\VCExpress\$VERSION)",
- "InstallDir", VSInstallPath, nullptr)) {
- if (!VSInstallPath.empty()) {
- llvm::SmallString<256> VCPath(llvm::StringRef(
- VSInstallPath.c_str(), VSInstallPath.find(R"(\Common7\IDE)")));
- llvm::sys::path::append(VCPath, "VC");
-
- Path = std::string(VCPath.str());
- VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
- return true;
- }
- }
- return false;
-}
-
// Try to find Exe from a Visual Studio distribution. This first tries to find
// an installed copy of Visual Studio and, failing that, looks in the PATH,
// making sure that whatever executable that's found is not a same-named exe
@@ -365,8 +59,8 @@ static bool findVCToolChainViaRegistry(std::string &Path,
static std::string FindVisualStudioExecutable(const ToolChain &TC,
const char *Exe) {
const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC);
- SmallString<128> FilePath(MSVC.getSubDirectoryPath(
- toolchains::MSVCToolChain::SubDirectoryType::Bin));
+ SmallString<128> FilePath(
+ MSVC.getSubDirectoryPath(llvm::SubDirectoryType::Bin));
llvm::sys::path::append(FilePath, Exe);
return std::string(canExecute(TC.getVFS(), FilePath) ? FilePath.str() : Exe);
}
@@ -386,7 +80,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.MakeArgString(std::string("-out:") + Output.getFilename()));
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) &&
- !C.getDriver().IsCLMode()) {
+ !C.getDriver().IsCLMode() && !C.getDriver().IsFlangMode()) {
CmdArgs.push_back("-defaultlib:libcmt");
CmdArgs.push_back("-defaultlib:oldnames");
}
@@ -396,17 +90,29 @@ 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",
+ llvm::archToLegacyVCArch(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)) {
CmdArgs.push_back(Args.MakeArgString(
Twine("-libpath:") +
- TC.getSubDirectoryPath(
- toolchains::MSVCToolChain::SubDirectoryType::Lib)));
+ TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib)));
CmdArgs.push_back(Args.MakeArgString(
Twine("-libpath:") +
- TC.getSubDirectoryPath(toolchains::MSVCToolChain::SubDirectoryType::Lib,
- "atlmfc")));
+ TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib, "atlmfc")));
}
if (!llvm::sys::Process::GetEnv("LIB") ||
Args.getLastArg(options::OPT__SLASH_winsdkdir,
@@ -423,6 +129,16 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath));
}
+ if (C.getDriver().IsFlangMode()) {
+ addFortranRuntimeLibraryPath(TC, Args, CmdArgs);
+ addFortranRuntimeLibs(TC, Args, CmdArgs);
+
+ // Inform the MSVC linker that we're generating a console application, i.e.
+ // one with `main` as the "user-defined" entry point. The `main` function is
+ // defined in flang's runtime libraries.
+ CmdArgs.push_back("/subsystem:console");
+ }
+
// Add the compiler-rt library directories to libpath if they exist to help
// the linker find the various sanitizer, builtin, and profiling runtimes.
for (const auto &LibPath : TC.getLibraryPaths()) {
@@ -442,6 +158,11 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7))
CmdArgs.push_back("-debug");
+ // If we specify /hotpatch, let the linker add padding in front of each
+ // function, like MSVC does.
+ if (Args.hasArg(options::OPT_fms_hotpatch, options::OPT__SLASH_hotpatch))
+ CmdArgs.push_back("-functionpadmin");
+
// Pass on /Brepro if it was passed to the compiler.
// Note that /Brepro maps to -mno-incremental-linker-compatible.
bool DefaultIncrementalLinkerCompatible =
@@ -461,7 +182,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 +193,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));
@@ -506,7 +227,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link);
// Control Flow Guard checks
- if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) {
+ for (const Arg *A : Args.filtered(options::OPT__SLASH_guard)) {
StringRef GuardArgs = A->getValue();
if (GuardArgs.equals_insensitive("cf") ||
GuardArgs.equals_insensitive("cf,nochecks")) {
@@ -548,6 +269,26 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
AddRunTimeLibs(TC, TC.getDriver(), CmdArgs, Args);
}
+ StringRef Linker =
+ Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER);
+ if (Linker.empty())
+ Linker = "link";
+ // We need to translate 'lld' into 'lld-link'.
+ else if (Linker.equals_insensitive("lld"))
+ Linker = "lld-link";
+
+ if (Linker == "lld-link") {
+ for (Arg *A : Args.filtered(options::OPT_vfsoverlay))
+ CmdArgs.push_back(
+ Args.MakeArgString(std::string("/vfsoverlay:") + A->getValue()));
+
+ if (C.getDriver().isUsingLTO() &&
+ Args.hasFlag(options::OPT_gsplit_dwarf, options::OPT_gno_split_dwarf,
+ false))
+ CmdArgs.push_back(Args.MakeArgString(Twine("/dwodir:") +
+ Output.getFilename() + "_dwo"));
+ }
+
// Add filenames, libraries, and other linker inputs.
for (const auto &Input : Inputs) {
if (Input.isFilename()) {
@@ -561,7 +302,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (A.getOption().matches(options::OPT_l)) {
StringRef Lib = A.getValue();
const char *LinkLibArg;
- if (Lib.endswith(".lib"))
+ if (Lib.ends_with(".lib"))
LinkLibArg = Args.MakeArgString(Lib);
else
LinkLibArg = Args.MakeArgString(Lib + ".lib");
@@ -574,21 +315,15 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
A.renderAsInput(Args, CmdArgs);
}
+ addHIPRuntimeLibArgs(TC, C, Args, CmdArgs);
+
TC.addProfileRTLibs(Args, CmdArgs);
std::vector<const char *> Environment;
- // We need to special case some linker paths. In the case of lld, we need to
- // translate 'lld' into 'lld-link', and in the case of the regular msvc
+ // We need to special case some linker paths. In the case of the regular msvc
// linker, we need to use a special search algorithm.
llvm::SmallString<128> linkPath;
- StringRef Linker
- = Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER);
- if (Linker.empty())
- Linker = "link";
- if (Linker.equals_insensitive("lld"))
- Linker = "lld-link";
-
if (Linker.equals_insensitive("link")) {
// If we're using the MSVC linker, it's not sufficient to just use link
// from the program PATH, because other environments like GnuWin32 install
@@ -608,13 +343,18 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ // Clang handles passing the proper asan libs to the linker, which goes
+ // against link.exe's /INFERASANLIBS which automatically finds asan libs.
+ if (TC.getSanitizerArgs(Args).needsAsanRt())
+ CmdArgs.push_back("/INFERASANLIBS:NO");
+
#ifdef _WIN32
// When cross-compiling with VS2017 or newer, link.exe expects to have
// its containing bin directory at the top of PATH, followed by the
// native target bin directory.
// e.g. when compiling for x86 on an x64 host, PATH should start with:
// /bin/Hostx64/x86;/bin/Hostx64/x64
- // This doesn't attempt to handle ToolsetLayout::DevDivInternal.
+ // This doesn't attempt to handle llvm::ToolsetLayout::DevDivInternal.
if (TC.getIsVS2017OrNewer() &&
llvm::Triple(llvm::sys::getProcessTriple()).getArch() != TC.getArch()) {
auto HostArch = llvm::Triple(llvm::sys::getProcessTriple()).getArch();
@@ -648,14 +388,13 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// find it.
for (const char *Cursor = EnvBlock.data(); *Cursor != '\0';) {
llvm::StringRef EnvVar(Cursor);
- if (EnvVar.startswith_insensitive("path=")) {
- using SubDirectoryType = toolchains::MSVCToolChain::SubDirectoryType;
+ if (EnvVar.starts_with_insensitive("path=")) {
constexpr size_t PrefixLen = 5; // strlen("path=")
Environment.push_back(Args.MakeArgString(
EnvVar.substr(0, PrefixLen) +
- TC.getSubDirectoryPath(SubDirectoryType::Bin) +
+ TC.getSubDirectoryPath(llvm::SubDirectoryType::Bin) +
llvm::Twine(llvm::sys::EnvPathSeparator) +
- TC.getSubDirectoryPath(SubDirectoryType::Bin, "", HostArch) +
+ TC.getSubDirectoryPath(llvm::SubDirectoryType::Bin, HostArch) +
(EnvVar.size() > PrefixLen
? llvm::Twine(llvm::sys::EnvPathSeparator) +
EnvVar.substr(PrefixLen)
@@ -688,14 +427,29 @@ MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
+ std::optional<llvm::StringRef> VCToolsDir, VCToolsVersion;
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir))
+ VCToolsDir = A->getValue();
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsversion))
+ VCToolsVersion = A->getValue();
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkdir))
+ WinSdkDir = A->getValue();
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkversion))
+ WinSdkVersion = A->getValue();
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsysroot))
+ WinSysRoot = A->getValue();
+
// Check the command line first, that's the user explicitly telling us what to
// use. Check the environment next, in case we're being invoked from a VS
// command prompt. Failing that, just try to find the newest Visual Studio
// version we can and use its default VC toolchain.
- findVCToolChainViaCommandLine(getVFS(), Args, VCToolChainPath, VSLayout) ||
- findVCToolChainViaEnvironment(getVFS(), VCToolChainPath, VSLayout) ||
- findVCToolChainViaSetupConfig(getVFS(), VCToolChainPath, VSLayout) ||
- findVCToolChainViaRegistry(VCToolChainPath, VSLayout);
+ llvm::findVCToolChainViaCommandLine(getVFS(), VCToolsDir, VCToolsVersion,
+ WinSysRoot, VCToolChainPath, VSLayout) ||
+ llvm::findVCToolChainViaEnvironment(getVFS(), VCToolChainPath,
+ VSLayout) ||
+ llvm::findVCToolChainViaSetupConfig(getVFS(), VCToolsVersion,
+ VCToolChainPath, VSLayout) ||
+ llvm::findVCToolChainViaRegistry(VCToolChainPath, VSLayout);
}
Tool *MSVCToolChain::buildLinker() const {
@@ -709,453 +463,104 @@ Tool *MSVCToolChain::buildAssembler() const {
return nullptr;
}
-bool MSVCToolChain::IsIntegratedAssemblerDefault() const {
- return true;
-}
-
-bool MSVCToolChain::IsUnwindTablesDefault(const ArgList &Args) const {
+ToolChain::UnwindTableLevel
+MSVCToolChain::getDefaultUnwindTableLevel(const ArgList &Args) const {
// Don't emit unwind tables by default for MachO targets.
if (getTriple().isOSBinFormatMachO())
- return false;
+ return UnwindTableLevel::None;
// All non-x86_32 Windows targets require unwind tables. However, LLVM
// doesn't know how to generate them for all targets, so only enable
// the ones that are actually implemented.
- return getArch() == llvm::Triple::x86_64 ||
- getArch() == llvm::Triple::aarch64;
+ if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::arm ||
+ getArch() == llvm::Triple::thumb || getArch() == llvm::Triple::aarch64)
+ return UnwindTableLevel::Asynchronous;
+
+ return UnwindTableLevel::None;
}
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,
ArgStringList &CC1Args) const {
- CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
+ CudaInstallation->AddCudaIncludeArgs(DriverArgs, CC1Args);
}
void MSVCToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
- RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
-}
-
-void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const {
- CudaInstallation.print(OS);
- RocmInstallation.print(OS);
+ RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args);
}
-// 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 "";
- }
+void MSVCToolChain::AddHIPRuntimeLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ CmdArgs.append({Args.MakeArgString(StringRef("-libpath:") +
+ RocmInstallation->getLibPath()),
+ "amdhip64.lib"});
}
-// 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 "";
- }
+void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const {
+ CudaInstallation->print(OS);
+ RocmInstallation->print(OS);
}
-// 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 "";
- }
+std::string
+MSVCToolChain::getSubDirectoryPath(llvm::SubDirectoryType Type,
+ llvm::StringRef SubdirParent) const {
+ return llvm::getSubDirectoryPath(Type, VSLayout, VCToolChainPath, getArch(),
+ SubdirParent);
}
-// Get the path to a specific subdirectory in the current toolchain for
-// a given target architecture.
-// VS2017 changed the VC toolchain layout, so this should be used instead
-// of hardcoding paths.
std::string
-MSVCToolChain::getSubDirectoryPath(SubDirectoryType Type,
- llvm::StringRef SubdirParent,
+MSVCToolChain::getSubDirectoryPath(llvm::SubDirectoryType Type,
llvm::Triple::ArchType TargetArch) const {
- const char *SubdirName;
- const char *IncludeName;
- switch (VSLayout) {
- case ToolsetLayout::OlderVS:
- SubdirName = llvmArchToLegacyVCArch(TargetArch);
- IncludeName = "include";
- break;
- case ToolsetLayout::VS2017OrNewer:
- SubdirName = llvmArchToWindowsSDKArch(TargetArch);
- IncludeName = "include";
- break;
- case ToolsetLayout::DevDivInternal:
- SubdirName = llvmArchToDevDivInternalArch(TargetArch);
- IncludeName = "inc";
- break;
- }
-
- llvm::SmallString<256> Path(VCToolChainPath);
- if (!SubdirParent.empty())
- llvm::sys::path::append(Path, SubdirParent);
-
- switch (Type) {
- case SubDirectoryType::Bin:
- if (VSLayout == ToolsetLayout::VS2017OrNewer) {
- const bool HostIsX64 =
- llvm::Triple(llvm::sys::getProcessTriple()).isArch64Bit();
- const char *const HostName = HostIsX64 ? "Hostx64" : "Hostx86";
- llvm::sys::path::append(Path, "bin", HostName, SubdirName);
- } else { // OlderVS or DevDivInternal
- llvm::sys::path::append(Path, "bin", SubdirName);
- }
- break;
- case SubDirectoryType::Include:
- llvm::sys::path::append(Path, IncludeName);
- break;
- case SubDirectoryType::Lib:
- llvm::sys::path::append(Path, "lib", SubdirName);
- break;
- }
- return std::string(Path.str());
-}
-
-#ifdef _WIN32
-static bool readFullStringValue(HKEY hkey, const char *valueName,
- std::string &value) {
- std::wstring WideValueName;
- if (!llvm::ConvertUTF8toWide(valueName, WideValueName))
- return false;
-
- DWORD result = 0;
- DWORD valueSize = 0;
- DWORD type = 0;
- // First just query for the required size.
- result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, &type, NULL,
- &valueSize);
- if (result != ERROR_SUCCESS || type != REG_SZ || !valueSize)
- return false;
- std::vector<BYTE> buffer(valueSize);
- result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, NULL, &buffer[0],
- &valueSize);
- if (result == ERROR_SUCCESS) {
- std::wstring WideValue(reinterpret_cast<const wchar_t *>(buffer.data()),
- valueSize / sizeof(wchar_t));
- if (valueSize && WideValue.back() == L'\0') {
- WideValue.pop_back();
- }
- // The destination buffer must be empty as an invariant of the conversion
- // function; but this function is sometimes called in a loop that passes in
- // the same buffer, however. Simply clear it out so we can overwrite it.
- value.clear();
- return llvm::convertWideToUTF8(WideValue, value);
- }
- return false;
-}
-#endif
-
-/// Read registry string.
-/// This also supports a means to look for high-versioned keys by use
-/// of a $VERSION placeholder in the key path.
-/// $VERSION in the key path is a placeholder for the version number,
-/// causing the highest value path to be searched for and used.
-/// I.e. "SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
-/// There can be additional characters in the component. Only the numeric
-/// characters are compared. This function only searches HKLM.
-static bool getSystemRegistryString(const char *keyPath, const char *valueName,
- std::string &value, std::string *phValue) {
-#ifndef _WIN32
- return false;
-#else
- HKEY hRootKey = HKEY_LOCAL_MACHINE;
- HKEY hKey = NULL;
- long lResult;
- bool returnValue = false;
-
- const char *placeHolder = strstr(keyPath, "$VERSION");
- std::string bestName;
- // If we have a $VERSION placeholder, do the highest-version search.
- if (placeHolder) {
- const char *keyEnd = placeHolder - 1;
- const char *nextKey = placeHolder;
- // Find end of previous key.
- while ((keyEnd > keyPath) && (*keyEnd != '\\'))
- keyEnd--;
- // Find end of key containing $VERSION.
- while (*nextKey && (*nextKey != '\\'))
- nextKey++;
- size_t partialKeyLength = keyEnd - keyPath;
- char partialKey[256];
- if (partialKeyLength >= sizeof(partialKey))
- partialKeyLength = sizeof(partialKey) - 1;
- strncpy(partialKey, keyPath, partialKeyLength);
- partialKey[partialKeyLength] = '\0';
- HKEY hTopKey = NULL;
- lResult = RegOpenKeyExA(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY,
- &hTopKey);
- if (lResult == ERROR_SUCCESS) {
- char keyName[256];
- double bestValue = 0.0;
- DWORD index, size = sizeof(keyName) - 1;
- for (index = 0; RegEnumKeyExA(hTopKey, index, keyName, &size, NULL, NULL,
- NULL, NULL) == ERROR_SUCCESS;
- index++) {
- const char *sp = keyName;
- while (*sp && !isDigit(*sp))
- sp++;
- if (!*sp)
- continue;
- const char *ep = sp + 1;
- while (*ep && (isDigit(*ep) || (*ep == '.')))
- ep++;
- char numBuf[32];
- strncpy(numBuf, sp, sizeof(numBuf) - 1);
- numBuf[sizeof(numBuf) - 1] = '\0';
- double dvalue = strtod(numBuf, NULL);
- if (dvalue > bestValue) {
- // Test that InstallDir is indeed there before keeping this index.
- // Open the chosen key path remainder.
- bestName = keyName;
- // Append rest of key.
- bestName.append(nextKey);
- lResult = RegOpenKeyExA(hTopKey, bestName.c_str(), 0,
- KEY_READ | KEY_WOW64_32KEY, &hKey);
- if (lResult == ERROR_SUCCESS) {
- if (readFullStringValue(hKey, valueName, value)) {
- bestValue = dvalue;
- if (phValue)
- *phValue = bestName;
- returnValue = true;
- }
- RegCloseKey(hKey);
- }
- }
- size = sizeof(keyName) - 1;
- }
- RegCloseKey(hTopKey);
- }
- } else {
- lResult =
- RegOpenKeyExA(hRootKey, keyPath, 0, KEY_READ | KEY_WOW64_32KEY, &hKey);
- if (lResult == ERROR_SUCCESS) {
- if (readFullStringValue(hKey, valueName, value))
- returnValue = true;
- if (phValue)
- phValue->clear();
- RegCloseKey(hKey);
- }
- }
- return returnValue;
-#endif // _WIN32
+ return llvm::getSubDirectoryPath(Type, VSLayout, VCToolChainPath, TargetArch,
+ "");
}
// Find the most recent version of Universal CRT or Windows 10 SDK.
// vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include
// directory by name and uses the last one of the list.
// So we compare entry names lexicographically to find the greatest one.
-static bool getWindows10SDKVersionFromPath(llvm::vfs::FileSystem &VFS,
- const std::string &SDKPath,
- std::string &SDKVersion) {
- llvm::SmallString<128> IncludePath(SDKPath);
- llvm::sys::path::append(IncludePath, "Include");
- SDKVersion = getHighestNumericTupleInDirectory(VFS, IncludePath);
- return !SDKVersion.empty();
-}
-
-static bool getWindowsSDKDirViaCommandLine(llvm::vfs::FileSystem &VFS,
- const ArgList &Args,
- std::string &Path, int &Major,
- std::string &Version) {
- if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkdir,
- options::OPT__SLASH_winsysroot)) {
- // Don't validate the input; trust the value supplied by the user.
- // The motivation is to prevent unnecessary file and registry access.
- llvm::VersionTuple SDKVersion;
- if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkversion))
- SDKVersion.tryParse(A->getValue());
-
- if (A->getOption().getID() == options::OPT__SLASH_winsysroot) {
- llvm::SmallString<128> SDKPath(A->getValue());
- llvm::sys::path::append(SDKPath, "Windows Kits");
- if (!SDKVersion.empty())
- llvm::sys::path::append(SDKPath, Twine(SDKVersion.getMajor()));
- else
- llvm::sys::path::append(
- SDKPath, getHighestNumericTupleInDirectory(VFS, SDKPath));
- Path = std::string(SDKPath.str());
- } else {
- Path = A->getValue();
- }
-
- if (!SDKVersion.empty()) {
- Major = SDKVersion.getMajor();
- Version = SDKVersion.getAsString();
- } else if (getWindows10SDKVersionFromPath(VFS, Path, Version)) {
- Major = 10;
- }
- return true;
- }
- return false;
-}
-
-/// Get Windows SDK installation directory.
-static bool getWindowsSDKDir(llvm::vfs::FileSystem &VFS, const ArgList &Args,
- std::string &Path, int &Major,
- std::string &WindowsSDKIncludeVersion,
- std::string &WindowsSDKLibVersion) {
- // Trust /winsdkdir and /winsdkversion if present.
- if (getWindowsSDKDirViaCommandLine(VFS, Args, Path, Major,
- WindowsSDKIncludeVersion)) {
- WindowsSDKLibVersion = WindowsSDKIncludeVersion;
- return true;
- }
-
- // FIXME: Try env vars (%WindowsSdkDir%, %UCRTVersion%) before going to registry.
-
- // Try the Windows registry.
- std::string RegistrySDKVersion;
- if (!getSystemRegistryString(
- "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
- "InstallationFolder", Path, &RegistrySDKVersion))
- return false;
- if (Path.empty() || RegistrySDKVersion.empty())
- return false;
-
- WindowsSDKIncludeVersion.clear();
- WindowsSDKLibVersion.clear();
- Major = 0;
- std::sscanf(RegistrySDKVersion.c_str(), "v%d.", &Major);
- if (Major <= 7)
- return true;
- if (Major == 8) {
- // Windows SDK 8.x installs libraries in a folder whose names depend on the
- // version of the OS you're targeting. By default choose the newest, which
- // usually corresponds to the version of the OS you've installed the SDK on.
- const char *Tests[] = {"winv6.3", "win8", "win7"};
- for (const char *Test : Tests) {
- llvm::SmallString<128> TestPath(Path);
- llvm::sys::path::append(TestPath, "Lib", Test);
- if (VFS.exists(TestPath)) {
- WindowsSDKLibVersion = Test;
- break;
- }
- }
- return !WindowsSDKLibVersion.empty();
- }
- if (Major == 10) {
- if (!getWindows10SDKVersionFromPath(VFS, Path, WindowsSDKIncludeVersion))
- return false;
- WindowsSDKLibVersion = WindowsSDKIncludeVersion;
- return true;
- }
- // Unsupported SDK version
- return false;
-}
-
// Gets the library path required to link against the Windows SDK.
-bool MSVCToolChain::getWindowsSDKLibraryPath(
- const ArgList &Args, std::string &path) const {
+bool MSVCToolChain::getWindowsSDKLibraryPath(const ArgList &Args,
+ std::string &path) const {
std::string sdkPath;
int sdkMajor = 0;
std::string windowsSDKIncludeVersion;
std::string windowsSDKLibVersion;
path.clear();
- if (!getWindowsSDKDir(getVFS(), Args, sdkPath, sdkMajor,
- windowsSDKIncludeVersion, windowsSDKLibVersion))
+ if (!llvm::getWindowsSDKDir(getVFS(), WinSdkDir, WinSdkVersion, WinSysRoot,
+ sdkPath, sdkMajor, windowsSDKIncludeVersion,
+ windowsSDKLibVersion))
return false;
llvm::SmallString<128> libPath(sdkPath);
llvm::sys::path::append(libPath, "Lib");
- if (sdkMajor >= 8) {
- llvm::sys::path::append(libPath, windowsSDKLibVersion, "um",
- llvmArchToWindowsSDKArch(getArch()));
- } else {
- switch (getArch()) {
- // In Windows SDK 7.x, x86 libraries are directly in the Lib folder.
- case llvm::Triple::x86:
- break;
- case llvm::Triple::x86_64:
- llvm::sys::path::append(libPath, "x64");
- break;
- case llvm::Triple::arm:
- // It is not necessary to link against Windows SDK 7.x when targeting ARM.
- return false;
- default:
- return false;
- }
- }
-
- path = std::string(libPath.str());
- return true;
+ if (sdkMajor >= 10)
+ if (!(WinSdkDir.has_value() || WinSysRoot.has_value()) &&
+ WinSdkVersion.has_value())
+ windowsSDKLibVersion = *WinSdkVersion;
+ if (sdkMajor >= 8)
+ llvm::sys::path::append(libPath, windowsSDKLibVersion, "um");
+ return llvm::appendArchToWindowsSDKLibPath(sdkMajor, libPath, getArch(),
+ path);
}
-// Check if the Include path of a specified version of Visual Studio contains
-// specific header files. If not, they are probably shipped with Universal CRT.
bool MSVCToolChain::useUniversalCRT() const {
- llvm::SmallString<128> TestPath(
- getSubDirectoryPath(SubDirectoryType::Include));
- llvm::sys::path::append(TestPath, "stdlib.h");
- return !getVFS().exists(TestPath);
-}
-
-static bool getUniversalCRTSdkDir(llvm::vfs::FileSystem &VFS,
- const ArgList &Args, std::string &Path,
- std::string &UCRTVersion) {
- // If /winsdkdir is passed, use it as location for the UCRT too.
- // FIXME: Should there be a dedicated /ucrtdir to override /winsdkdir?
- int Major;
- if (getWindowsSDKDirViaCommandLine(VFS, Args, Path, Major, UCRTVersion))
- return true;
-
- // FIXME: Try env vars (%UniversalCRTSdkDir%, %UCRTVersion%) before going to
- // registry.
-
- // vcvarsqueryregistry.bat for Visual Studio 2015 queries the registry
- // for the specific key "KitsRoot10". So do we.
- if (!getSystemRegistryString(
- "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot10",
- Path, nullptr))
- return false;
-
- return getWindows10SDKVersionFromPath(VFS, Path, UCRTVersion);
+ return llvm::useUniversalCRT(VSLayout, VCToolChainPath, getArch(), getVFS());
}
bool MSVCToolChain::getUniversalCRTLibraryPath(const ArgList &Args,
@@ -1164,28 +569,26 @@ bool MSVCToolChain::getUniversalCRTLibraryPath(const ArgList &Args,
std::string UCRTVersion;
Path.clear();
- if (!getUniversalCRTSdkDir(getVFS(), Args, UniversalCRTSdkPath, UCRTVersion))
+ if (!llvm::getUniversalCRTSdkDir(getVFS(), WinSdkDir, WinSdkVersion,
+ WinSysRoot, UniversalCRTSdkPath,
+ UCRTVersion))
return false;
- StringRef ArchName = llvmArchToWindowsSDKArch(getArch());
+ if (!(WinSdkDir.has_value() || WinSysRoot.has_value()) &&
+ WinSdkVersion.has_value())
+ UCRTVersion = *WinSdkVersion;
+
+ StringRef ArchName = llvm::archToWindowsSDKArch(getArch());
if (ArchName.empty())
return false;
llvm::SmallString<128> LibPath(UniversalCRTSdkPath);
llvm::sys::path::append(LibPath, "Lib", UCRTVersion, "ucrt", ArchName);
- Path = std::string(LibPath.str());
+ Path = std::string(LibPath);
return true;
}
-static VersionTuple getMSVCVersionFromTriple(const llvm::Triple &Triple) {
- unsigned Major, Minor, Micro;
- Triple.getEnvironmentVersion(Major, Minor, Micro);
- if (Major || Minor || Micro)
- return VersionTuple(Major, Minor, Micro);
- return VersionTuple();
-}
-
static VersionTuple getMSVCVersionFromExe(const std::string &BinDir) {
VersionTuple Version;
#ifdef _WIN32
@@ -1263,6 +666,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;
@@ -1280,15 +696,20 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
// the correct include paths first.
if (!VCToolChainPath.empty()) {
addSystemInclude(DriverArgs, CC1Args,
- getSubDirectoryPath(SubDirectoryType::Include));
- addSystemInclude(DriverArgs, CC1Args,
- getSubDirectoryPath(SubDirectoryType::Include, "atlmfc"));
+ getSubDirectoryPath(llvm::SubDirectoryType::Include));
+ addSystemInclude(
+ DriverArgs, CC1Args,
+ getSubDirectoryPath(llvm::SubDirectoryType::Include, "atlmfc"));
if (useUniversalCRT()) {
std::string UniversalCRTSdkPath;
std::string UCRTVersion;
- if (getUniversalCRTSdkDir(getVFS(), DriverArgs, UniversalCRTSdkPath,
- UCRTVersion)) {
+ if (llvm::getUniversalCRTSdkDir(getVFS(), WinSdkDir, WinSdkVersion,
+ WinSysRoot, UniversalCRTSdkPath,
+ UCRTVersion)) {
+ if (!(WinSdkDir.has_value() || WinSysRoot.has_value()) &&
+ WinSdkVersion.has_value())
+ UCRTVersion = *WinSdkVersion;
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath,
"Include", UCRTVersion, "ucrt");
}
@@ -1298,8 +719,13 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
int major = 0;
std::string windowsSDKIncludeVersion;
std::string windowsSDKLibVersion;
- if (getWindowsSDKDir(getVFS(), DriverArgs, WindowsSDKDir, major,
- windowsSDKIncludeVersion, windowsSDKLibVersion)) {
+ if (llvm::getWindowsSDKDir(getVFS(), WinSdkDir, WinSdkVersion, WinSysRoot,
+ WindowsSDKDir, major, windowsSDKIncludeVersion,
+ windowsSDKLibVersion)) {
+ if (major >= 10)
+ if (!(WinSdkDir.has_value() || WinSysRoot.has_value()) &&
+ WinSdkVersion.has_value())
+ windowsSDKIncludeVersion = windowsSDKLibVersion = *WinSdkVersion;
if (major >= 8) {
// Note: windowsSDKIncludeVersion is empty for SDKs prior to v10.
// Anyway, llvm::sys::path::append is able to manage it.
@@ -1312,6 +738,15 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
"Include", windowsSDKIncludeVersion,
"winrt");
+ if (major >= 10) {
+ llvm::VersionTuple Tuple;
+ if (!Tuple.tryParse(windowsSDKIncludeVersion) &&
+ Tuple.getSubminor().value_or(0) >= 17134) {
+ AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
+ "Include", windowsSDKIncludeVersion,
+ "cppwinrt");
+ }
+ }
} else {
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
"Include");
@@ -1345,14 +780,18 @@ VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D,
bool IsWindowsMSVC = getTriple().isWindowsMSVCEnvironment();
VersionTuple MSVT = ToolChain::computeMSVCVersion(D, Args);
if (MSVT.empty())
- MSVT = getMSVCVersionFromTriple(getTriple());
+ MSVT = getTriple().getEnvironmentVersion();
if (MSVT.empty() && IsWindowsMSVC)
- MSVT = getMSVCVersionFromExe(getSubDirectoryPath(SubDirectoryType::Bin));
+ MSVT =
+ getMSVCVersionFromExe(getSubDirectoryPath(llvm::SubDirectoryType::Bin));
if (MSVT.empty() &&
Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
IsWindowsMSVC)) {
- // -fms-compatibility-version=19.14 is default, aka 2017, 15.7
- MSVT = VersionTuple(19, 14);
+ // -fms-compatibility-version=19.33 is default, aka 2022, 17.3
+ // NOTE: when changing this value, also update
+ // clang/docs/CommandGuide/clang.rst and clang/docs/UsersManual.rst
+ // accordingly.
+ MSVT = VersionTuple(19, 33);
}
return MSVT;
}
@@ -1363,8 +802,8 @@ MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
// The MSVC version doesn't care about the architecture, even though it
// may look at the triple internally.
VersionTuple MSVT = computeMSVCVersion(/*D=*/nullptr, Args);
- MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().getValueOr(0),
- MSVT.getSubminor().getValueOr(0));
+ MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().value_or(0),
+ MSVT.getSubminor().value_or(0));
// For the rest of the triple, however, a computed architecture name may
// be needed.
@@ -1577,7 +1016,7 @@ void MSVCToolChain::addClangTargetOptions(
Action::OffloadKind DeviceOffloadKind) const {
// MSVC STL kindly allows removing all usages of typeid by defining
// _HAS_STATIC_RTTI to 0. Do so, when compiling with -fno-rtti
- if (DriverArgs.hasArg(options::OPT_fno_rtti, options::OPT_frtti,
- /*Default=*/false))
+ if (DriverArgs.hasFlag(options::OPT_fno_rtti, options::OPT_frtti,
+ /*Default=*/false))
CC1Args.push_back("-D_HAS_STATIC_RTTI=0");
}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/MSVC.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/MSVC.h
index 19d94c5c606e..48369e030aad 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/MSVC.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/MSVC.h
@@ -11,10 +11,12 @@
#include "AMDGPU.h"
#include "Cuda.h"
-#include "clang/Basic/DebugInfoOptions.h"
+#include "LazyDetector.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
+#include "llvm/Frontend/Debug/Options.h"
+#include "llvm/WindowsDriver/MSVCPaths.h"
namespace clang {
namespace driver {
@@ -22,7 +24,7 @@ namespace tools {
/// Visual studio tools.
namespace visualstudio {
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
public:
Linker(const ToolChain &TC) : Tool("visualstudio::Linker", "linker", TC) {}
@@ -49,18 +51,19 @@ public:
TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
Action::OffloadKind DeviceOffloadKind) const override;
- bool IsIntegratedAssemblerDefault() const override;
- bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override;
+ UnwindTableLevel
+ getDefaultUnwindTableLevel(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
/// formats, and to DWARF otherwise. Users can use -gcodeview and -gdwarf to
/// override the default.
- codegenoptions::DebugInfoFormat getDefaultDebugFormat() const override {
- return getTriple().isOSBinFormatMachO() ? codegenoptions::DIF_DWARF
- : codegenoptions::DIF_CodeView;
+ llvm::codegenoptions::DebugInfoFormat getDefaultDebugFormat() const override {
+ return getTriple().isOSBinFormatMachO()
+ ? llvm::codegenoptions::DIF_DWARF
+ : llvm::codegenoptions::DIF_CodeView;
}
/// Set the debugger tuning to "default", since we're definitely not tuning
@@ -69,29 +72,19 @@ public:
return llvm::DebuggerKind::Default;
}
- enum class SubDirectoryType {
- Bin,
- Include,
- Lib,
- };
- std::string getSubDirectoryPath(SubDirectoryType Type,
- llvm::StringRef SubdirParent,
+ unsigned GetDefaultDwarfVersion() const override {
+ return 4;
+ }
+
+ std::string getSubDirectoryPath(llvm::SubDirectoryType Type,
+ llvm::StringRef SubdirParent = "") const;
+ std::string getSubDirectoryPath(llvm::SubDirectoryType Type,
llvm::Triple::ArchType TargetArch) const;
- // Convenience overload.
- // Uses the current target arch.
- std::string getSubDirectoryPath(SubDirectoryType Type,
- llvm::StringRef SubdirParent = "") const {
- return getSubDirectoryPath(Type, SubdirParent, getArch());
+ bool getIsVS2017OrNewer() const {
+ return VSLayout == llvm::ToolsetLayout::VS2017OrNewer;
}
- enum class ToolsetLayout {
- OlderVS,
- VS2017OrNewer,
- DevDivInternal,
- };
- bool getIsVS2017OrNewer() const { return VSLayout == ToolsetLayout::VS2017OrNewer; }
-
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
@@ -105,6 +98,9 @@ public:
void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+ void AddHIPRuntimeLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+
bool getWindowsSDKLibraryPath(
const llvm::opt::ArgList &Args, std::string &path) const;
bool getUniversalCRTLibraryPath(const llvm::opt::ArgList &Args,
@@ -138,10 +134,11 @@ protected:
Tool *buildLinker() const override;
Tool *buildAssembler() const override;
private:
+ std::optional<llvm::StringRef> WinSdkDir, WinSdkVersion, WinSysRoot;
std::string VCToolChainPath;
- ToolsetLayout VSLayout = ToolsetLayout::OlderVS;
- CudaInstallationDetector CudaInstallation;
- RocmInstallationDetector RocmInstallation;
+ llvm::ToolsetLayout VSLayout = llvm::ToolsetLayout::OlderVS;
+ LazyDetector<CudaInstallationDetector> CudaInstallation;
+ LazyDetector<RocmInstallationDetector> RocmInstallation;
};
} // end namespace toolchains
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/MSVCSetupApi.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/MSVCSetupApi.h
deleted file mode 100644
index a890b85fd5e9..000000000000
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/MSVCSetupApi.h
+++ /dev/null
@@ -1,514 +0,0 @@
-// <copyright file="Program.cpp" company="Microsoft Corporation">
-// Copyright (C) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-// </copyright>
-// <license>
-// The MIT License (MIT)
-//
-// Copyright (C) Microsoft Corporation. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-// </license>
-
-#pragma once
-
-// Constants
-//
-#ifndef E_NOTFOUND
-#define E_NOTFOUND HRESULT_FROM_WIN32(ERROR_NOT_FOUND)
-#endif
-
-#ifndef E_FILENOTFOUND
-#define E_FILENOTFOUND HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)
-#endif
-
-// Enumerations
-//
-/// <summary>
-/// The state of an instance.
-/// </summary>
-enum InstanceState : unsigned {
- /// <summary>
- /// The instance state has not been determined.
- /// </summary>
- eNone = 0,
-
- /// <summary>
- /// The instance installation path exists.
- /// </summary>
- eLocal = 1,
-
- /// <summary>
- /// A product is registered to the instance.
- /// </summary>
- eRegistered = 2,
-
- /// <summary>
- /// No reboot is required for the instance.
- /// </summary>
- eNoRebootRequired = 4,
-
- /// <summary>
- /// The instance represents a complete install.
- /// </summary>
- eComplete = MAXUINT,
-};
-
-// Forward interface declarations
-//
-#ifndef __ISetupInstance_FWD_DEFINED__
-#define __ISetupInstance_FWD_DEFINED__
-typedef struct ISetupInstance ISetupInstance;
-#endif
-
-#ifndef __ISetupInstance2_FWD_DEFINED__
-#define __ISetupInstance2_FWD_DEFINED__
-typedef struct ISetupInstance2 ISetupInstance2;
-#endif
-
-#ifndef __IEnumSetupInstances_FWD_DEFINED__
-#define __IEnumSetupInstances_FWD_DEFINED__
-typedef struct IEnumSetupInstances IEnumSetupInstances;
-#endif
-
-#ifndef __ISetupConfiguration_FWD_DEFINED__
-#define __ISetupConfiguration_FWD_DEFINED__
-typedef struct ISetupConfiguration ISetupConfiguration;
-#endif
-
-#ifndef __ISetupConfiguration2_FWD_DEFINED__
-#define __ISetupConfiguration2_FWD_DEFINED__
-typedef struct ISetupConfiguration2 ISetupConfiguration2;
-#endif
-
-#ifndef __ISetupPackageReference_FWD_DEFINED__
-#define __ISetupPackageReference_FWD_DEFINED__
-typedef struct ISetupPackageReference ISetupPackageReference;
-#endif
-
-#ifndef __ISetupHelper_FWD_DEFINED__
-#define __ISetupHelper_FWD_DEFINED__
-typedef struct ISetupHelper ISetupHelper;
-#endif
-
-// Forward class declarations
-//
-#ifndef __SetupConfiguration_FWD_DEFINED__
-#define __SetupConfiguration_FWD_DEFINED__
-
-#ifdef __cplusplus
-typedef class SetupConfiguration SetupConfiguration;
-#endif
-
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Interface definitions
-//
-EXTERN_C const IID IID_ISetupInstance;
-
-#if defined(__cplusplus) && !defined(CINTERFACE)
-/// <summary>
-/// Information about an instance of a product.
-/// </summary>
-struct DECLSPEC_UUID("B41463C3-8866-43B5-BC33-2B0676F7F42E")
- DECLSPEC_NOVTABLE ISetupInstance : public IUnknown {
- /// <summary>
- /// Gets the instance identifier (should match the name of the parent instance
- /// directory).
- /// </summary>
- /// <param name="pbstrInstanceId">The instance identifier.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist.</returns>
- STDMETHOD(GetInstanceId)(_Out_ BSTR *pbstrInstanceId) = 0;
-
- /// <summary>
- /// Gets the local date and time when the installation was originally
- /// installed.
- /// </summary>
- /// <param name="pInstallDate">The local date and time when the installation
- /// was originally installed.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
- /// property is not defined.</returns>
- STDMETHOD(GetInstallDate)(_Out_ LPFILETIME pInstallDate) = 0;
-
- /// <summary>
- /// Gets the unique name of the installation, often indicating the branch and
- /// other information used for telemetry.
- /// </summary>
- /// <param name="pbstrInstallationName">The unique name of the installation,
- /// often indicating the branch and other information used for
- /// telemetry.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
- /// property is not defined.</returns>
- STDMETHOD(GetInstallationName)(_Out_ BSTR *pbstrInstallationName) = 0;
-
- /// <summary>
- /// Gets the path to the installation root of the product.
- /// </summary>
- /// <param name="pbstrInstallationPath">The path to the installation root of
- /// the product.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
- /// property is not defined.</returns>
- STDMETHOD(GetInstallationPath)(_Out_ BSTR *pbstrInstallationPath) = 0;
-
- /// <summary>
- /// Gets the version of the product installed in this instance.
- /// </summary>
- /// <param name="pbstrInstallationVersion">The version of the product
- /// installed in this instance.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
- /// property is not defined.</returns>
- STDMETHOD(GetInstallationVersion)(_Out_ BSTR *pbstrInstallationVersion) = 0;
-
- /// <summary>
- /// Gets the display name (title) of the product installed in this instance.
- /// </summary>
- /// <param name="lcid">The LCID for the display name.</param>
- /// <param name="pbstrDisplayName">The display name (title) of the product
- /// installed in this instance.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
- /// property is not defined.</returns>
- STDMETHOD(GetDisplayName)(_In_ LCID lcid, _Out_ BSTR *pbstrDisplayName) = 0;
-
- /// <summary>
- /// Gets the description of the product installed in this instance.
- /// </summary>
- /// <param name="lcid">The LCID for the description.</param>
- /// <param name="pbstrDescription">The description of the product installed in
- /// this instance.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
- /// property is not defined.</returns>
- STDMETHOD(GetDescription)(_In_ LCID lcid, _Out_ BSTR *pbstrDescription) = 0;
-
- /// <summary>
- /// Resolves the optional relative path to the root path of the instance.
- /// </summary>
- /// <param name="pwszRelativePath">A relative path within the instance to
- /// resolve, or NULL to get the root path.</param>
- /// <param name="pbstrAbsolutePath">The full path to the optional relative
- /// path within the instance. If the relative path is NULL, the root path will
- /// always terminate in a backslash.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
- /// property is not defined.</returns>
- STDMETHOD(ResolvePath)
- (_In_opt_z_ LPCOLESTR pwszRelativePath, _Out_ BSTR *pbstrAbsolutePath) = 0;
-};
-#endif
-
-EXTERN_C const IID IID_ISetupInstance2;
-
-#if defined(__cplusplus) && !defined(CINTERFACE)
-/// <summary>
-/// Information about an instance of a product.
-/// </summary>
-struct DECLSPEC_UUID("89143C9A-05AF-49B0-B717-72E218A2185C")
- DECLSPEC_NOVTABLE ISetupInstance2 : public ISetupInstance {
- /// <summary>
- /// Gets the state of the instance.
- /// </summary>
- /// <param name="pState">The state of the instance.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist.</returns>
- STDMETHOD(GetState)(_Out_ InstanceState *pState) = 0;
-
- /// <summary>
- /// Gets an array of package references registered to the instance.
- /// </summary>
- /// <param name="ppsaPackages">Pointer to an array of <see
- /// cref="ISetupPackageReference"/>.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
- /// packages property is not defined.</returns>
- STDMETHOD(GetPackages)(_Out_ LPSAFEARRAY *ppsaPackages) = 0;
-
- /// <summary>
- /// Gets a pointer to the <see cref="ISetupPackageReference"/> that represents
- /// the registered product.
- /// </summary>
- /// <param name="ppPackage">Pointer to an instance of <see
- /// cref="ISetupPackageReference"/>. This may be NULL if <see
- /// cref="GetState"/> does not return <see cref="eComplete"/>.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
- /// packages property is not defined.</returns>
- STDMETHOD(GetProduct)
- (_Outptr_result_maybenull_ ISetupPackageReference **ppPackage) = 0;
-
- /// <summary>
- /// Gets the relative path to the product application, if available.
- /// </summary>
- /// <param name="pbstrProductPath">The relative path to the product
- /// application, if available.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist.</returns>
- STDMETHOD(GetProductPath)
- (_Outptr_result_maybenull_ BSTR *pbstrProductPath) = 0;
-};
-#endif
-
-EXTERN_C const IID IID_IEnumSetupInstances;
-
-#if defined(__cplusplus) && !defined(CINTERFACE)
-/// <summary>
-/// A enumerator of installed <see cref="ISetupInstance"/> objects.
-/// </summary>
-struct DECLSPEC_UUID("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848")
- DECLSPEC_NOVTABLE IEnumSetupInstances : public IUnknown {
- /// <summary>
- /// Retrieves the next set of product instances in the enumeration sequence.
- /// </summary>
- /// <param name="celt">The number of product instances to retrieve.</param>
- /// <param name="rgelt">A pointer to an array of <see
- /// cref="ISetupInstance"/>.</param>
- /// <param name="pceltFetched">A pointer to the number of product instances
- /// retrieved. If celt is 1 this parameter may be NULL.</param>
- /// <returns>S_OK if the number of elements were fetched, S_FALSE if nothing
- /// was fetched (at end of enumeration), E_INVALIDARG if celt is greater than
- /// 1 and pceltFetched is NULL, or E_OUTOFMEMORY if an <see
- /// cref="ISetupInstance"/> could not be allocated.</returns>
- STDMETHOD(Next)
- (_In_ ULONG celt, _Out_writes_to_(celt, *pceltFetched) ISetupInstance **rgelt,
- _Out_opt_ _Deref_out_range_(0, celt) ULONG *pceltFetched) = 0;
-
- /// <summary>
- /// Skips the next set of product instances in the enumeration sequence.
- /// </summary>
- /// <param name="celt">The number of product instances to skip.</param>
- /// <returns>S_OK if the number of elements could be skipped; otherwise,
- /// S_FALSE;</returns>
- STDMETHOD(Skip)(_In_ ULONG celt) = 0;
-
- /// <summary>
- /// Resets the enumeration sequence to the beginning.
- /// </summary>
- /// <returns>Always returns S_OK;</returns>
- STDMETHOD(Reset)(void) = 0;
-
- /// <summary>
- /// Creates a new enumeration object in the same state as the current
- /// enumeration object: the new object points to the same place in the
- /// enumeration sequence.
- /// </summary>
- /// <param name="ppenum">A pointer to a pointer to a new <see
- /// cref="IEnumSetupInstances"/> interface. If the method fails, this
- /// parameter is undefined.</param>
- /// <returns>S_OK if a clone was returned; otherwise, E_OUTOFMEMORY.</returns>
- STDMETHOD(Clone)(_Deref_out_opt_ IEnumSetupInstances **ppenum) = 0;
-};
-#endif
-
-EXTERN_C const IID IID_ISetupConfiguration;
-
-#if defined(__cplusplus) && !defined(CINTERFACE)
-/// <summary>
-/// Gets information about product instances set up on the machine.
-/// </summary>
-struct DECLSPEC_UUID("42843719-DB4C-46C2-8E7C-64F1816EFD5B")
- DECLSPEC_NOVTABLE ISetupConfiguration : public IUnknown {
- /// <summary>
- /// Enumerates all completed product instances installed.
- /// </summary>
- /// <param name="ppEnumInstances">An enumeration of completed, installed
- /// product instances.</param>
- /// <returns>Standard HRESULT indicating success or failure.</returns>
- STDMETHOD(EnumInstances)(_Out_ IEnumSetupInstances **ppEnumInstances) = 0;
-
- /// <summary>
- /// Gets the instance for the current process path.
- /// </summary>
- /// <param name="ppInstance">The instance for the current process
- /// path.</param>
- /// <returns>The instance for the current process path, or E_NOTFOUND if not
- /// found.</returns>
- STDMETHOD(GetInstanceForCurrentProcess)
- (_Out_ ISetupInstance **ppInstance) = 0;
-
- /// <summary>
- /// Gets the instance for the given path.
- /// </summary>
- /// <param name="ppInstance">The instance for the given path.</param>
- /// <returns>The instance for the given path, or E_NOTFOUND if not
- /// found.</returns>
- STDMETHOD(GetInstanceForPath)
- (_In_z_ LPCWSTR wzPath, _Out_ ISetupInstance **ppInstance) = 0;
-};
-#endif
-
-EXTERN_C const IID IID_ISetupConfiguration2;
-
-#if defined(__cplusplus) && !defined(CINTERFACE)
-/// <summary>
-/// Gets information about product instances.
-/// </summary>
-struct DECLSPEC_UUID("26AAB78C-4A60-49D6-AF3B-3C35BC93365D")
- DECLSPEC_NOVTABLE ISetupConfiguration2 : public ISetupConfiguration {
- /// <summary>
- /// Enumerates all product instances.
- /// </summary>
- /// <param name="ppEnumInstances">An enumeration of all product
- /// instances.</param>
- /// <returns>Standard HRESULT indicating success or failure.</returns>
- STDMETHOD(EnumAllInstances)(_Out_ IEnumSetupInstances **ppEnumInstances) = 0;
-};
-#endif
-
-EXTERN_C const IID IID_ISetupPackageReference;
-
-#if defined(__cplusplus) && !defined(CINTERFACE)
-/// <summary>
-/// A reference to a package.
-/// </summary>
-struct DECLSPEC_UUID("da8d8a16-b2b6-4487-a2f1-594ccccd6bf5")
- DECLSPEC_NOVTABLE ISetupPackageReference : public IUnknown {
- /// <summary>
- /// Gets the general package identifier.
- /// </summary>
- /// <param name="pbstrId">The general package identifier.</param>
- /// <returns>Standard HRESULT indicating success or failure.</returns>
- STDMETHOD(GetId)(_Out_ BSTR *pbstrId) = 0;
-
- /// <summary>
- /// Gets the version of the package.
- /// </summary>
- /// <param name="pbstrVersion">The version of the package.</param>
- /// <returns>Standard HRESULT indicating success or failure.</returns>
- STDMETHOD(GetVersion)(_Out_ BSTR *pbstrVersion) = 0;
-
- /// <summary>
- /// Gets the target process architecture of the package.
- /// </summary>
- /// <param name="pbstrChip">The target process architecture of the
- /// package.</param>
- /// <returns>Standard HRESULT indicating success or failure.</returns>
- STDMETHOD(GetChip)(_Out_ BSTR *pbstrChip) = 0;
-
- /// <summary>
- /// Gets the language and optional region identifier.
- /// </summary>
- /// <param name="pbstrLanguage">The language and optional region
- /// identifier.</param>
- /// <returns>Standard HRESULT indicating success or failure.</returns>
- STDMETHOD(GetLanguage)(_Out_ BSTR *pbstrLanguage) = 0;
-
- /// <summary>
- /// Gets the build branch of the package.
- /// </summary>
- /// <param name="pbstrBranch">The build branch of the package.</param>
- /// <returns>Standard HRESULT indicating success or failure.</returns>
- STDMETHOD(GetBranch)(_Out_ BSTR *pbstrBranch) = 0;
-
- /// <summary>
- /// Gets the type of the package.
- /// </summary>
- /// <param name="pbstrType">The type of the package.</param>
- /// <returns>Standard HRESULT indicating success or failure.</returns>
- STDMETHOD(GetType)(_Out_ BSTR *pbstrType) = 0;
-
- /// <summary>
- /// Gets the unique identifier consisting of all defined tokens.
- /// </summary>
- /// <param name="pbstrUniqueId">The unique identifier consisting of all
- /// defined tokens.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_UNEXPECTED if no Id was defined (required).</returns>
- STDMETHOD(GetUniqueId)(_Out_ BSTR *pbstrUniqueId) = 0;
-};
-#endif
-
-EXTERN_C const IID IID_ISetupHelper;
-
-#if defined(__cplusplus) && !defined(CINTERFACE)
-/// <summary>
-/// Helper functions.
-/// </summary>
-/// <remarks>
-/// You can query for this interface from the <see cref="SetupConfiguration"/>
-/// class.
-/// </remarks>
-struct DECLSPEC_UUID("42b21b78-6192-463e-87bf-d577838f1d5c")
- DECLSPEC_NOVTABLE ISetupHelper : public IUnknown {
- /// <summary>
- /// Parses a dotted quad version string into a 64-bit unsigned integer.
- /// </summary>
- /// <param name="pwszVersion">The dotted quad version string to parse, e.g.
- /// 1.2.3.4.</param>
- /// <param name="pullVersion">A 64-bit unsigned integer representing the
- /// version. You can compare this to other versions.</param>
- /// <returns>Standard HRESULT indicating success or failure.</returns>
- STDMETHOD(ParseVersion)
- (_In_ LPCOLESTR pwszVersion, _Out_ PULONGLONG pullVersion) = 0;
-
- /// <summary>
- /// Parses a dotted quad version string into a 64-bit unsigned integer.
- /// </summary>
- /// <param name="pwszVersionRange">The string containing 1 or 2 dotted quad
- /// version strings to parse, e.g. [1.0,) that means 1.0.0.0 or newer.</param>
- /// <param name="pullMinVersion">A 64-bit unsigned integer representing the
- /// minimum version, which may be 0. You can compare this to other
- /// versions.</param>
- /// <param name="pullMaxVersion">A 64-bit unsigned integer representing the
- /// maximum version, which may be MAXULONGLONG. You can compare this to other
- /// versions.</param>
- /// <returns>Standard HRESULT indicating success or failure.</returns>
- STDMETHOD(ParseVersionRange)
- (_In_ LPCOLESTR pwszVersionRange, _Out_ PULONGLONG pullMinVersion,
- _Out_ PULONGLONG pullMaxVersion) = 0;
-};
-#endif
-
-// Class declarations
-//
-EXTERN_C const CLSID CLSID_SetupConfiguration;
-
-#ifdef __cplusplus
-/// <summary>
-/// This class implements <see cref="ISetupConfiguration"/>, <see
-/// cref="ISetupConfiguration2"/>, and <see cref="ISetupHelper"/>.
-/// </summary>
-class DECLSPEC_UUID("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D") SetupConfiguration;
-#endif
-
-// Function declarations
-//
-/// <summary>
-/// Gets an <see cref="ISetupConfiguration"/> that provides information about
-/// product instances installed on the machine.
-/// </summary>
-/// <param name="ppConfiguration">The <see cref="ISetupConfiguration"/> that
-/// provides information about product instances installed on the
-/// machine.</param>
-/// <param name="pReserved">Reserved for future use.</param>
-/// <returns>Standard HRESULT indicating success or failure.</returns>
-STDMETHODIMP GetSetupConfiguration(_Out_ ISetupConfiguration **ppConfiguration,
- _Reserved_ LPVOID pReserved);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/MinGW.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/MinGW.cpp
index 7ba729f36bd8..067758c05e97 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/MinGW.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/MinGW.cpp
@@ -86,7 +86,9 @@ void tools::MinGW::Linker::AddLibGCC(const ArgList &Args,
CmdArgs.push_back("-lmoldname");
CmdArgs.push_back("-lmingwex");
for (auto Lib : Args.getAllArgValues(options::OPT_l))
- if (StringRef(Lib).startswith("msvcr") || StringRef(Lib).startswith("ucrt"))
+ if (StringRef(Lib).starts_with("msvcr") ||
+ StringRef(Lib).starts_with("ucrt") ||
+ StringRef(Lib).starts_with("crtdll"))
return;
CmdArgs.push_back("-lmsvcrt");
}
@@ -98,7 +100,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;
@@ -133,7 +135,7 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("arm64pe");
break;
default:
- llvm_unreachable("Unsupported target architecture.");
+ D.Diag(diag::err_target_unknown_triple) << TC.getEffectiveTriple().str();
}
Arg *SubsysArg =
@@ -164,6 +166,24 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("--enable-auto-image-base");
}
+ if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
+ CmdArgs.push_back("--no-demangle");
+
+ if (!Args.hasFlag(options::OPT_fauto_import, options::OPT_fno_auto_import,
+ true))
+ CmdArgs.push_back("--disable-auto-import");
+
+ if (Arg *A = Args.getLastArg(options::OPT_mguard_EQ)) {
+ StringRef GuardArgs = A->getValue();
+ if (GuardArgs == "none")
+ CmdArgs.push_back("--no-guard-cf");
+ else if (GuardArgs == "cf" || GuardArgs == "cf-nochecks")
+ CmdArgs.push_back("--guard-cf");
+ else
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getSpelling() << GuardArgs;
+ }
+
CmdArgs.push_back("-o");
const char *OutputFile = Output.getFilename();
// GCC implicitly adds an .exe extension if it is given an output file name
@@ -176,13 +196,21 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
} else
CmdArgs.push_back(OutputFile);
- Args.AddAllArgs(CmdArgs, options::OPT_e);
// FIXME: add -N, -n flags
Args.AddLastArg(CmdArgs, options::OPT_r);
Args.AddLastArg(CmdArgs, options::OPT_s);
Args.AddLastArg(CmdArgs, options::OPT_t);
Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
- Args.AddLastArg(CmdArgs, options::OPT_Z_Flag);
+
+ // Add asan_dynamic as the first import lib before other libs. This allows
+ // asan to be initialized as early as possible to increase its instrumentation
+ // coverage to include other user DLLs which has not been built with asan.
+ if (Sanitize.needsAsanRt() && !Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ // MinGW always links against a shared MSVCRT.
+ CmdArgs.push_back(
+ TC.getCompilerRTArgString(Args, "asan_dynamic", ToolChain::FT_Shared));
+ }
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_mdll)) {
@@ -213,6 +241,17 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
+ if (D.isUsingLTO()) {
+ assert(!Inputs.empty() && "Must have at least one input.");
+ addLTOOptions(TC, Args, CmdArgs, Output, Inputs[0],
+ D.getLTOMode() == LTOK_Thin);
+ }
+
+ if (C.getDriver().IsFlangMode()) {
+ addFortranRuntimeLibraryPath(TC, Args, CmdArgs);
+ addFortranRuntimeLibs(TC, Args, CmdArgs);
+ }
+
// TODO: Add profile stuff here
if (TC.ShouldLinkCXXStdlib(Args)) {
@@ -327,10 +366,20 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Exec, CmdArgs, Inputs, Output));
}
+static bool isCrossCompiling(const llvm::Triple &T, bool RequireArchMatch) {
+ llvm::Triple HostTriple(llvm::Triple::normalize(LLVM_HOST_TRIPLE));
+ if (HostTriple.getOS() != llvm::Triple::Win32)
+ return true;
+ if (RequireArchMatch && HostTriple.getArch() != T.getArch())
+ return true;
+ return false;
+}
+
// Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple.
static bool findGccVersion(StringRef LibDir, std::string &GccLibDir,
- std::string &Ver) {
- auto Version = toolchains::Generic_GCC::GCCVersion::Parse("0.0.0");
+ std::string &Ver,
+ toolchains::Generic_GCC::GCCVersion &Version) {
+ Version = toolchains::Generic_GCC::GCCVersion::Parse("0.0.0");
std::error_code EC;
for (llvm::sys::fs::directory_iterator LI(LibDir, EC), LE; !EC && LI != LE;
LI = LI.increment(EC)) {
@@ -348,31 +397,51 @@ static bool findGccVersion(StringRef LibDir, std::string &GccLibDir,
return Ver.size();
}
-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());
+static llvm::Triple getLiteralTriple(const Driver &D, const llvm::Triple &T) {
+ llvm::Triple LiteralTriple(D.getTargetTriple());
+ // The arch portion of the triple may be overridden by -m32/-m64.
+ LiteralTriple.setArchName(T.getArchName());
+ return LiteralTriple;
+}
+
+void toolchains::MinGW::findGccLibDir(const llvm::Triple &LiteralTriple) {
+ llvm::SmallVector<llvm::SmallString<32>, 5> SubdirNames;
+ SubdirNames.emplace_back(LiteralTriple.str());
+ SubdirNames.emplace_back(getTriple().str());
+ SubdirNames.emplace_back(getTriple().getArchName());
+ SubdirNames.back() += "-w64-mingw32";
+ SubdirNames.emplace_back(getTriple().getArchName());
+ SubdirNames.back() += "-w64-mingw32ucrt";
+ SubdirNames.emplace_back("mingw32");
+ if (SubdirName.empty()) {
+ SubdirName = getTriple().getArchName();
+ SubdirName += "-w64-mingw32";
+ }
// 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);
- if (findGccVersion(LibDir, GccLibDir, Ver)) {
- Arch = std::string(CandidateArch);
+ llvm::sys::path::append(LibDir, CandidateLib, "gcc", CandidateSysroot);
+ if (findGccVersion(LibDir, GccLibDir, Ver, GccVer)) {
+ SubdirName = std::string(CandidateSysroot);
return;
}
}
}
}
-llvm::ErrorOr<std::string> toolchains::MinGW::findGcc() {
- llvm::SmallVector<llvm::SmallString<32>, 2> Gccs;
- Gccs.emplace_back(getTriple().getArchName());
- Gccs[0] += "-w64-mingw32-gcc";
+static llvm::ErrorOr<std::string> findGcc(const llvm::Triple &LiteralTriple,
+ const llvm::Triple &T) {
+ llvm::SmallVector<llvm::SmallString<32>, 5> Gccs;
+ Gccs.emplace_back(LiteralTriple.str());
+ Gccs.back() += "-gcc";
+ Gccs.emplace_back(T.str());
+ Gccs.back() += "-gcc";
+ Gccs.emplace_back(T.getArchName());
+ Gccs.back() += "-w64-mingw32-gcc";
+ Gccs.emplace_back(T.getArchName());
+ Gccs.back() += "-w64-mingw32ucrt-gcc";
Gccs.emplace_back("mingw32-gcc");
// Please do not add "gcc" here
for (StringRef CandidateGcc : Gccs)
@@ -381,60 +450,98 @@ 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() {
- llvm::SmallVector<llvm::SmallString<32>, 2> Subdirs;
- Subdirs.emplace_back(getTriple().str());
- Subdirs.emplace_back(getTriple().getArchName());
- Subdirs[1] += "-w64-mingw32";
- StringRef ClangRoot =
- llvm::sys::path::parent_path(getDriver().getInstalledDir());
+static llvm::ErrorOr<std::string>
+findClangRelativeSysroot(const Driver &D, const llvm::Triple &LiteralTriple,
+ const llvm::Triple &T, std::string &SubdirName) {
+ llvm::SmallVector<llvm::SmallString<32>, 4> Subdirs;
+ Subdirs.emplace_back(LiteralTriple.str());
+ Subdirs.emplace_back(T.str());
+ Subdirs.emplace_back(T.getArchName());
+ Subdirs.back() += "-w64-mingw32";
+ Subdirs.emplace_back(T.getArchName());
+ Subdirs.back() += "-w64-mingw32ucrt";
+ 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();
}
}
return make_error_code(std::errc::no_such_file_or_directory);
}
+static bool looksLikeMinGWSysroot(const std::string &Directory) {
+ StringRef Sep = llvm::sys::path::get_separator();
+ if (!llvm::sys::fs::exists(Directory + Sep + "include" + Sep + "_mingw.h"))
+ return false;
+ if (!llvm::sys::fs::exists(Directory + Sep + "lib" + Sep + "libkernel32.a"))
+ return false;
+ return true;
+}
+
toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args),
RocmInstallation(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
+ std::string InstallBase =
+ std::string(llvm::sys::path::parent_path(getDriver().getInstalledDir()));
+ // The sequence for detecting a sysroot here should be kept in sync with
+ // the testTriple function below.
+ llvm::Triple LiteralTriple = getLiteralTriple(D, getTriple());
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(), LiteralTriple, getTriple(), SubdirName))
Base = std::string(llvm::sys::path::parent_path(TargetSubdir.get()));
- else if (llvm::ErrorOr<std::string> GPPName = findGcc())
+ // If the install base of Clang seems to have mingw sysroot files directly
+ // in the toplevel include and lib directories, use this as base instead of
+ // looking for a triple prefixed GCC in the path.
+ else if (looksLikeMinGWSysroot(InstallBase))
+ Base = InstallBase;
+ else if (llvm::ErrorOr<std::string> GPPName =
+ findGcc(LiteralTriple, getTriple()))
Base = std::string(llvm::sys::path::parent_path(
llvm::sys::path::parent_path(GPPName.get())));
else
- Base = std::string(
- llvm::sys::path::parent_path(getDriver().getInstalledDir()));
+ Base = InstallBase;
Base += llvm::sys::path::get_separator();
- findGccLibDir();
+ findGccLibDir(LiteralTriple);
+ TripleDirName = SubdirName;
// GccLibDir must precede Base/lib so that the
// correct crtbegin.o ,cetend.o would be found.
getFilePaths().push_back(GccLibDir);
+
+ // openSUSE/Fedora
+ std::string CandidateSubdir = SubdirName + "/sys-root/mingw";
+ if (getDriver().getVFS().exists(Base + CandidateSubdir))
+ SubdirName = CandidateSubdir;
+
+ getFilePaths().push_back(
+ (Base + SubdirName + llvm::sys::path::get_separator() + "lib").str());
+
+ // Gentoo
getFilePaths().push_back(
- (Base + Arch + llvm::sys::path::get_separator() + "lib").str());
- getFilePaths().push_back(Base + "lib");
- // openSUSE
- getFilePaths().push_back(Base + Arch + "/sys-root/mingw/lib");
+ (Base + SubdirName + llvm::sys::path::get_separator() + "mingw/lib").str());
+
+ // Only include <base>/lib if we're not cross compiling (not even for
+ // windows->windows to a different arch), or if the sysroot has been set
+ // (where we presume the user has pointed it at an arch specific
+ // subdirectory).
+ if (!::isCrossCompiling(getTriple(), /*RequireArchMatch=*/true) ||
+ getDriver().SysRoot.size())
+ getFilePaths().push_back(Base + "lib");
NativeLLVMSupport =
Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER)
.equals_insensitive("lld");
}
-bool toolchains::MinGW::IsIntegratedAssemblerDefault() const { return true; }
-
Tool *toolchains::MinGW::getTool(Action::ActionClass AC) const {
switch (AC) {
case Action::PreprocessJobClass:
@@ -462,30 +569,36 @@ bool toolchains::MinGW::HasNativeLLVMSupport() const {
return NativeLLVMSupport;
}
-bool toolchains::MinGW::IsUnwindTablesDefault(const ArgList &Args) const {
+ToolChain::UnwindTableLevel
+toolchains::MinGW::getDefaultUnwindTableLevel(const ArgList &Args) const {
Arg *ExceptionArg = Args.getLastArg(options::OPT_fsjlj_exceptions,
options::OPT_fseh_exceptions,
options::OPT_fdwarf_exceptions);
if (ExceptionArg &&
ExceptionArg->getOption().matches(options::OPT_fseh_exceptions))
- return true;
- return getArch() == llvm::Triple::x86_64 ||
- getArch() == llvm::Triple::aarch64;
+ return UnwindTableLevel::Asynchronous;
+
+ if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::arm ||
+ getArch() == llvm::Triple::thumb || getArch() == llvm::Triple::aarch64)
+ return UnwindTableLevel::Asynchronous;
+ return UnwindTableLevel::None;
}
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::isPICDefaultForced() const {
- return getArch() == llvm::Triple::x86_64;
+bool toolchains::MinGW::isPIEDefault(const llvm::opt::ArgList &Args) const {
+ return false;
}
+bool toolchains::MinGW::isPICDefaultForced() const { return true; }
+
llvm::ExceptionHandling
toolchains::MinGW::GetExceptionModel(const ArgList &Args) const {
- if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::aarch64)
+ if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::aarch64 ||
+ getArch() == llvm::Triple::arm || getArch() == llvm::Triple::thumb)
return llvm::ExceptionHandling::WinEH;
return llvm::ExceptionHandling::DwarfCFI;
}
@@ -501,17 +614,17 @@ SanitizerMask toolchains::MinGW::getSupportedSanitizers() const {
void toolchains::MinGW::AddCudaIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
- CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
+ CudaInstallation->AddCudaIncludeArgs(DriverArgs, CC1Args);
}
void toolchains::MinGW::AddHIPIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
- RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
+ RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args);
}
void toolchains::MinGW::printVerboseInfo(raw_ostream &OS) const {
- CudaInstallation.print(OS);
- RocmInstallation.print(OS);
+ CudaInstallation->print(OS);
+ RocmInstallation->print(OS);
}
// Include directories for various hosts:
@@ -554,6 +667,12 @@ void toolchains::MinGW::printVerboseInfo(raw_ostream &OS) const {
// /usr/include/c++/4.8/backward
// /usr/x86_64-w64-mingw32/include
+// Fedora
+// /usr/x86_64-w64-mingw32ucrt/sys-root/mingw/include/c++/x86_64-w64-mingw32ucrt
+// /usr/x86_64-w64-mingw32ucrt/sys-root/mingw/include/c++/backward
+// /usr/x86_64-w64-mingw32ucrt/sys-root/mingw/include
+// /usr/lib/gcc/x86_64-w64-mingw32ucrt/12.2.1/include-fixed
+
void toolchains::MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdinc))
@@ -568,49 +687,159 @@ void toolchains::MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
if (DriverArgs.hasArg(options::OPT_nostdlibinc))
return;
- if (GetRuntimeLibType(DriverArgs) == ToolChain::RLT_Libgcc) {
- // openSUSE
- addSystemInclude(DriverArgs, CC1Args,
- Base + Arch + "/sys-root/mingw/include");
- }
+ addSystemInclude(DriverArgs, CC1Args,
+ Base + SubdirName + llvm::sys::path::get_separator() +
+ "include");
+ // Gentoo
addSystemInclude(DriverArgs, CC1Args,
- Base + Arch + llvm::sys::path::get_separator() + "include");
- addSystemInclude(DriverArgs, CC1Args, Base + "include");
+ Base + SubdirName + llvm::sys::path::get_separator() + "usr/include");
+
+ // Only include <base>/include if we're not cross compiling (but do allow it
+ // if we're on Windows and building for Windows on another architecture),
+ // or if the sysroot has been set (where we presume the user has pointed it
+ // at an arch specific subdirectory).
+ if (!::isCrossCompiling(getTriple(), /*RequireArchMatch=*/false) ||
+ getDriver().SysRoot.size())
+ addSystemInclude(DriverArgs, CC1Args, Base + "include");
+}
+
+void toolchains::MinGW::addClangTargetOptions(
+ const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadKind) const {
+ if (Arg *A = DriverArgs.getLastArg(options::OPT_mguard_EQ)) {
+ StringRef GuardArgs = A->getValue();
+ if (GuardArgs == "none") {
+ // Do nothing.
+ } else if (GuardArgs == "cf") {
+ // Emit CFG instrumentation and the table of address-taken functions.
+ CC1Args.push_back("-cfguard");
+ } else if (GuardArgs == "cf-nochecks") {
+ // Emit only the table of address-taken functions.
+ CC1Args.push_back("-cfguard-no-checks");
+ } else {
+ getDriver().Diag(diag::err_drv_unsupported_option_argument)
+ << A->getSpelling() << GuardArgs;
+ }
+ }
+
+ CC1Args.push_back("-fno-use-init-array");
+
+ for (auto Opt : {options::OPT_mthreads, options::OPT_mwindows,
+ options::OPT_mconsole, options::OPT_mdll}) {
+ if (Arg *A = DriverArgs.getLastArgNoClaim(Opt))
+ A->ignoreTargetSpecific();
+ }
}
void toolchains::MinGW::AddClangCXXStdlibIncludeArgs(
const ArgList &DriverArgs, ArgStringList &CC1Args) const {
- if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
- DriverArgs.hasArg(options::OPT_nostdincxx))
+ if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc,
+ options::OPT_nostdincxx))
return;
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;
+ llvm::SmallVector<llvm::SmallString<1024>, 7> 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);
llvm::sys::path::append(CppIncludeBases[3], "include", "c++");
+ CppIncludeBases.emplace_back(GccLibDir);
+ llvm::sys::path::append(CppIncludeBases[4], "include",
+ "g++-v" + GccVer.Text);
+ CppIncludeBases.emplace_back(GccLibDir);
+ llvm::sys::path::append(CppIncludeBases[5], "include",
+ "g++-v" + GccVer.MajorStr + "." + GccVer.MinorStr);
+ CppIncludeBases.emplace_back(GccLibDir);
+ llvm::sys::path::append(CppIncludeBases[6], "include",
+ "g++-v" + GccVer.MajorStr);
for (auto &CppIncludeBase : CppIncludeBases) {
addSystemInclude(DriverArgs, CC1Args, CppIncludeBase);
CppIncludeBase += Slash;
- addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + Arch);
+ addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + TripleDirName);
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;
+ llvm::Triple LiteralTriple = getLiteralTriple(D, Triple);
+ std::string InstallBase =
+ std::string(llvm::sys::path::parent_path(D.getInstalledDir()));
+ if (llvm::ErrorOr<std::string> TargetSubdir =
+ findClangRelativeSysroot(D, LiteralTriple, Triple, SubdirName))
+ return true;
+ // If the install base itself looks like a mingw sysroot, we'll use that
+ // - don't use any potentially unrelated gcc to influence what triple to use.
+ if (looksLikeMinGWSysroot(InstallBase))
+ return false;
+ if (llvm::ErrorOr<std::string> GPPName = findGcc(LiteralTriple, 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/contrib/llvm-project/clang/lib/Driver/ToolChains/MinGW.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/MinGW.h
index 2f1559fcf34c..a9963d8d06c2 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/MinGW.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/MinGW.h
@@ -11,6 +11,7 @@
#include "Cuda.h"
#include "Gnu.h"
+#include "LazyDetector.h"
#include "ROCm.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
@@ -20,7 +21,7 @@ namespace clang {
namespace driver {
namespace tools {
-/// MinGW -- Directly call GNU Binutils assembler and linker
+/// Directly call GNU Binutils assembler and linker
namespace MinGW {
class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
public:
@@ -34,7 +35,7 @@ public:
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
public:
Linker(const ToolChain &TC) : Tool("MinGW::Linker", "linker", TC) {}
@@ -60,12 +61,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;
+ UnwindTableLevel
+ getDefaultUnwindTableLevel(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;
@@ -76,6 +80,10 @@ public:
void
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;
void AddClangCXXStdlibIncludeArgs(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
@@ -87,24 +95,26 @@ public:
void printVerboseInfo(raw_ostream &OS) const override;
+ unsigned GetDefaultDwarfVersion() const override { return 4; }
+
protected:
Tool *getTool(Action::ActionClass AC) const override;
Tool *buildLinker() const override;
Tool *buildAssembler() const override;
private:
- CudaInstallationDetector CudaInstallation;
- RocmInstallationDetector RocmInstallation;
+ LazyDetector<CudaInstallationDetector> CudaInstallation;
+ LazyDetector<RocmInstallationDetector> RocmInstallation;
std::string Base;
std::string GccLibDir;
+ clang::driver::toolchains::Generic_GCC::GCCVersion GccVer;
std::string Ver;
- std::string Arch;
+ std::string SubdirName;
+ std::string TripleDirName;
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();
+ void findGccLibDir(const llvm::Triple &LiteralTriple);
bool NativeLLVMSupport;
};
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Minix.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Minix.cpp
deleted file mode 100644
index 5bceb9aba3e9..000000000000
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Minix.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-//===--- Minix.cpp - Minix ToolChain Implementations ------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "Minix.h"
-#include "CommonArgs.h"
-#include "clang/Driver/Compilation.h"
-#include "clang/Driver/Driver.h"
-#include "clang/Driver/InputInfo.h"
-#include "clang/Driver/Options.h"
-#include "llvm/Option/ArgList.h"
-#include "llvm/Support/VirtualFileSystem.h"
-
-using namespace clang::driver;
-using namespace clang;
-using namespace llvm::opt;
-
-void tools::minix::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
- claimNoWarnArgs(Args);
- ArgStringList CmdArgs;
-
- Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
-
- CmdArgs.push_back("-o");
- CmdArgs.push_back(Output.getFilename());
-
- for (const auto &II : Inputs)
- CmdArgs.push_back(II.getFilename());
-
- const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
- C.addCommand(std::make_unique<Command>(JA, *this,
- ResponseFileSupport::AtFileCurCP(),
- Exec, CmdArgs, Inputs, Output));
-}
-
-void tools::minix::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();
- ArgStringList CmdArgs;
-
- if (Output.isFilename()) {
- CmdArgs.push_back("-o");
- CmdArgs.push_back(Output.getFilename());
- } else {
- assert(Output.isNothing() && "Invalid output.");
- }
-
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
- }
-
- Args.AddAllArgs(CmdArgs,
- {options::OPT_L, options::OPT_T_Group, options::OPT_e});
-
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
-
- getToolChain().addProfileRTLibs(Args, CmdArgs);
-
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
- if (D.CCCIsCXX()) {
- if (getToolChain().ShouldLinkCXXStdlib(Args))
- getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
- CmdArgs.push_back("-lm");
- }
- }
-
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
- if (Args.hasArg(options::OPT_pthread))
- CmdArgs.push_back("-lpthread");
- CmdArgs.push_back("-lc");
- CmdArgs.push_back("-lCompilerRT-Generic");
- CmdArgs.push_back("-L/usr/pkg/compiler-rt/lib");
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
- }
-
- const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
- C.addCommand(std::make_unique<Command>(JA, *this,
- ResponseFileSupport::AtFileCurCP(),
- Exec, CmdArgs, Inputs, Output));
-}
-
-/// Minix - Minix tool chain which can call as(1) and ld(1) directly.
-
-toolchains::Minix::Minix(const Driver &D, const llvm::Triple &Triple,
- const ArgList &Args)
- : Generic_ELF(D, Triple, Args) {
- getFilePaths().push_back(getDriver().Dir + "/../lib");
- getFilePaths().push_back("/usr/lib");
-}
-
-Tool *toolchains::Minix::buildAssembler() const {
- return new tools::minix::Assembler(*this);
-}
-
-Tool *toolchains::Minix::buildLinker() const {
- return new tools::minix::Linker(*this);
-}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Minix.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Minix.h
deleted file mode 100644
index af8d59c5085a..000000000000
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Minix.h
+++ /dev/null
@@ -1,64 +0,0 @@
-//===--- Minix.h - Minix ToolChain Implementations --------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MINIX_H
-#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MINIX_H
-
-#include "Gnu.h"
-#include "clang/Driver/Tool.h"
-#include "clang/Driver/ToolChain.h"
-
-namespace clang {
-namespace driver {
-namespace tools {
-/// minix -- Directly call GNU Binutils assembler and linker
-namespace minix {
-class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
-public:
- Assembler(const ToolChain &TC) : Tool("minix::Assembler", "assembler", TC) {}
-
- bool hasIntegratedCPP() const override { return false; }
-
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
-};
-
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
-public:
- Linker(const ToolChain &TC) : Tool("minix::Linker", "linker", TC) {}
-
- bool hasIntegratedCPP() const override { return false; }
- bool isLinkJob() const override { return true; }
-
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
-};
-} // end namespace minix
-} // end namespace tools
-
-namespace toolchains {
-
-class LLVM_LIBRARY_VISIBILITY Minix : public Generic_ELF {
-public:
- Minix(const Driver &D, const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args);
-
-protected:
- Tool *buildAssembler() const override;
- Tool *buildLinker() const override;
-};
-
-} // end namespace toolchains
-} // end namespace driver
-} // end namespace clang
-
-#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MINIX_H
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/MipsLinux.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/MipsLinux.cpp
index 41b7b839f3b3..4183eccceedb 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/MipsLinux.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/MipsLinux.cpp
@@ -30,7 +30,7 @@ MipsLLVMToolChain::MipsLLVMToolChain(const Driver &D,
DetectedMultilibs Result;
findMIPSMultilibs(D, Triple, "", Args, Result);
Multilibs = Result.Multilibs;
- SelectedMultilib = Result.SelectedMultilib;
+ SelectedMultilibs = Result.SelectedMultilibs;
// Find out the library suffix based on the ABI.
LibSuffix = tools::mips::getMipsABILibSuffix(Args, Triple);
@@ -56,7 +56,7 @@ void MipsLLVMToolChain::AddClangSystemIncludeArgs(
const auto &Callback = Multilibs.includeDirsCallback();
if (Callback) {
- for (const auto &Path : Callback(SelectedMultilib))
+ for (const auto &Path : Callback(SelectedMultilibs.back()))
addExternCSystemIncludeIfExists(DriverArgs, CC1Args,
D.getInstalledDir() + Path);
}
@@ -68,11 +68,11 @@ Tool *MipsLLVMToolChain::buildLinker() const {
std::string MipsLLVMToolChain::computeSysRoot() const {
if (!getDriver().SysRoot.empty())
- return getDriver().SysRoot + SelectedMultilib.osSuffix();
+ return getDriver().SysRoot + SelectedMultilibs.back().osSuffix();
const std::string InstalledDir(getDriver().getInstalledDir());
std::string SysRootPath =
- InstalledDir + "/../sysroot" + SelectedMultilib.osSuffix();
+ InstalledDir + "/../sysroot" + SelectedMultilibs.back().osSuffix();
if (llvm::sys::fs::exists(SysRootPath))
return SysRootPath;
@@ -96,7 +96,7 @@ void MipsLLVMToolChain::addLibCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
if (const auto &Callback = Multilibs.includeDirsCallback()) {
- for (std::string Path : Callback(SelectedMultilib)) {
+ for (std::string Path : Callback(SelectedMultilibs.back())) {
Path = getDriver().getInstalledDir() + Path + "/c++/v1";
if (llvm::sys::fs::exists(Path)) {
addSystemInclude(DriverArgs, CC1Args, Path);
@@ -112,6 +112,8 @@ void MipsLLVMToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
"Only -lc++ (aka libxx) is supported in this toolchain.");
CmdArgs.push_back("-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back("-lc++abi");
CmdArgs.push_back("-lunwind");
}
@@ -120,7 +122,7 @@ std::string MipsLLVMToolChain::getCompilerRT(const ArgList &Args,
StringRef Component,
FileType Type) const {
SmallString<128> Path(getDriver().ResourceDir);
- llvm::sys::path::append(Path, SelectedMultilib.osSuffix(), "lib" + LibSuffix,
+ llvm::sys::path::append(Path, SelectedMultilibs.back().osSuffix(), "lib" + LibSuffix,
getOS());
const char *Suffix;
switch (Type) {
@@ -136,5 +138,5 @@ std::string MipsLLVMToolChain::getCompilerRT(const ArgList &Args,
}
llvm::sys::path::append(
Path, Twine("libclang_rt." + Component + "-" + "mips" + Suffix));
- return std::string(Path.str());
+ return std::string(Path);
}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/MipsLinux.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/MipsLinux.h
index 31b547c0063c..a968804f2a6e 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/MipsLinux.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/MipsLinux.h
@@ -53,7 +53,6 @@ public:
}
private:
- Multilib SelectedMultilib;
std::string LibSuffix;
};
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Myriad.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Myriad.cpp
deleted file mode 100644
index f31466633104..000000000000
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Myriad.cpp
+++ /dev/null
@@ -1,293 +0,0 @@
-//===--- Myriad.cpp - Myriad ToolChain Implementations ----------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "Myriad.h"
-#include "CommonArgs.h"
-#include "clang/Driver/Compilation.h"
-#include "clang/Driver/Driver.h"
-#include "clang/Driver/DriverDiagnostic.h"
-#include "clang/Driver/Options.h"
-#include "llvm/Option/ArgList.h"
-
-using namespace clang::driver;
-using namespace clang::driver::toolchains;
-using namespace clang;
-using namespace llvm::opt;
-
-using tools::addPathIfExists;
-
-void tools::SHAVE::Compiler::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
- ArgStringList CmdArgs;
- assert(Inputs.size() == 1);
- const InputInfo &II = Inputs[0];
- assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX ||
- II.getType() == types::TY_PP_CXX);
-
- if (JA.getKind() == Action::PreprocessJobClass) {
- Args.ClaimAllArgs();
- CmdArgs.push_back("-E");
- } else {
- assert(Output.getType() == types::TY_PP_Asm); // Require preprocessed asm.
- CmdArgs.push_back("-S");
- CmdArgs.push_back("-fno-exceptions"); // Always do this even if unspecified.
- }
- CmdArgs.push_back("-DMYRIAD2");
-
- // Append all -I, -iquote, -isystem paths, defines/undefines, 'f'
- // flags, 'g' flags, 'M' flags, optimize flags, warning options,
- // mcpu flags, mllvm flags, and Xclang flags.
- // These are spelled the same way in clang and moviCompile.
- Args.AddAllArgsExcept(
- CmdArgs,
- {options::OPT_I_Group, options::OPT_clang_i_Group, options::OPT_std_EQ,
- options::OPT_D, options::OPT_U, options::OPT_f_Group,
- options::OPT_f_clang_Group, options::OPT_g_Group, options::OPT_M_Group,
- options::OPT_O_Group, options::OPT_W_Group, options::OPT_mcpu_EQ,
- options::OPT_mllvm, options::OPT_Xclang},
- {options::OPT_fno_split_dwarf_inlining});
- Args.hasArg(options::OPT_fno_split_dwarf_inlining); // Claim it if present.
-
- // If we're producing a dependency file, and assembly is the final action,
- // then the name of the target in the dependency file should be the '.o'
- // file, not the '.s' file produced by this step. For example, instead of
- // /tmp/mumble.s: mumble.c .../someheader.h
- // the filename on the lefthand side should be "mumble.o"
- if (Args.getLastArg(options::OPT_MF) && !Args.getLastArg(options::OPT_MT) &&
- C.getActions().size() == 1 &&
- C.getActions()[0]->getKind() == Action::AssembleJobClass) {
- Arg *A = Args.getLastArg(options::OPT_o);
- if (A) {
- CmdArgs.push_back("-MT");
- CmdArgs.push_back(Args.MakeArgString(A->getValue()));
- }
- }
-
- CmdArgs.push_back(II.getFilename());
- CmdArgs.push_back("-o");
- CmdArgs.push_back(Output.getFilename());
-
- std::string Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("moviCompile"));
- C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
- Args.MakeArgString(Exec), CmdArgs,
- Inputs, Output));
-}
-
-void tools::SHAVE::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
- ArgStringList CmdArgs;
-
- assert(Inputs.size() == 1);
- const InputInfo &II = Inputs[0];
- assert(II.getType() == types::TY_PP_Asm); // Require preprocessed asm input.
- assert(Output.getType() == types::TY_Object);
-
- CmdArgs.push_back("-no6thSlotCompression");
- const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ);
- if (CPUArg)
- CmdArgs.push_back(
- Args.MakeArgString("-cv:" + StringRef(CPUArg->getValue())));
- CmdArgs.push_back("-noSPrefixing");
- CmdArgs.push_back("-a"); // Mystery option.
- Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
- for (const Arg *A : Args.filtered(options::OPT_I, options::OPT_isystem)) {
- A->claim();
- CmdArgs.push_back(
- Args.MakeArgString(std::string("-i:") + A->getValue(0)));
- }
- CmdArgs.push_back(II.getFilename());
- CmdArgs.push_back(
- Args.MakeArgString(std::string("-o:") + Output.getFilename()));
-
- std::string Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("moviAsm"));
- C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
- Args.MakeArgString(Exec), CmdArgs,
- Inputs, Output));
-}
-
-void tools::Myriad::Linker::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
- const auto &TC =
- static_cast<const toolchains::MyriadToolChain &>(getToolChain());
- const llvm::Triple &T = TC.getTriple();
- ArgStringList CmdArgs;
- bool UseStartfiles =
- !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles);
- bool UseDefaultLibs =
- !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs);
- // Silence warning if the args contain both -nostdlib and -stdlib=.
- Args.getLastArg(options::OPT_stdlib_EQ);
-
- if (T.getArch() == llvm::Triple::sparc)
- CmdArgs.push_back("-EB");
- else // SHAVE assumes little-endian, and sparcel is expressly so.
- CmdArgs.push_back("-EL");
-
- // The remaining logic is mostly like gnutools::Linker::ConstructJob,
- // but we never pass through a --sysroot option and various other bits.
- // For example, there are no sanitizers (yet) nor gold linker.
-
- // Eat some arguments that may be present but have no effect.
- Args.ClaimAllArgs(options::OPT_g_Group);
- Args.ClaimAllArgs(options::OPT_w);
- Args.ClaimAllArgs(options::OPT_static_libgcc);
-
- if (Args.hasArg(options::OPT_s)) // Pass the 'strip' option.
- CmdArgs.push_back("-s");
-
- CmdArgs.push_back("-o");
- CmdArgs.push_back(Output.getFilename());
-
- if (UseStartfiles) {
- // If you want startfiles, it means you want the builtin crti and crtbegin,
- // but not crt0. Myriad link commands provide their own crt0.o as needed.
- CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crti.o")));
- CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o")));
- }
-
- Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
- options::OPT_e, options::OPT_s, options::OPT_t,
- options::OPT_Z_Flag, options::OPT_r});
-
- TC.AddFilePathLibArgs(Args, CmdArgs);
-
- bool NeedsSanitizerDeps = addSanitizerRuntimes(TC, Args, CmdArgs);
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
-
- if (UseDefaultLibs) {
- if (NeedsSanitizerDeps)
- linkSanitizerRuntimeDeps(TC, CmdArgs);
- if (C.getDriver().CCCIsCXX()) {
- if (TC.GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) {
- CmdArgs.push_back("-lc++");
- CmdArgs.push_back("-lc++abi");
- } else
- CmdArgs.push_back("-lstdc++");
- }
- if (T.getOS() == llvm::Triple::RTEMS) {
- CmdArgs.push_back("--start-group");
- CmdArgs.push_back("-lc");
- CmdArgs.push_back("-lgcc"); // circularly dependent on rtems
- // You must provide your own "-L" option to enable finding these.
- CmdArgs.push_back("-lrtemscpu");
- CmdArgs.push_back("-lrtemsbsp");
- CmdArgs.push_back("--end-group");
- } else {
- CmdArgs.push_back("-lc");
- CmdArgs.push_back("-lgcc");
- }
- }
- if (UseStartfiles) {
- CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o")));
- CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtn.o")));
- }
-
- std::string Exec =
- Args.MakeArgString(TC.GetProgramPath("sparc-myriad-rtems-ld"));
- C.addCommand(std::make_unique<Command>(
- JA, *this, ResponseFileSupport::AtFileCurCP(), Args.MakeArgString(Exec),
- CmdArgs, Inputs, Output));
-}
-
-MyriadToolChain::MyriadToolChain(const Driver &D, const llvm::Triple &Triple,
- const ArgList &Args)
- : Generic_ELF(D, Triple, Args) {
- // If a target of 'sparc-myriad-elf' is specified to clang, it wants to use
- // 'sparc-myriad--elf' (note the unknown OS) as the canonical triple.
- // This won't work to find gcc. Instead we give the installation detector an
- // extra triple, which is preferable to further hacks of the logic that at
- // present is based solely on getArch(). In particular, it would be wrong to
- // choose the myriad installation when targeting a non-myriad sparc install.
- switch (Triple.getArch()) {
- default:
- D.Diag(clang::diag::err_target_unsupported_arch)
- << Triple.getArchName() << "myriad";
- LLVM_FALLTHROUGH;
- case llvm::Triple::shave:
- return;
- case llvm::Triple::sparc:
- case llvm::Triple::sparcel:
- GCCInstallation.init(Triple, Args, {"sparc-myriad-rtems"});
- }
-
- if (GCCInstallation.isValid()) {
- // This directory contains crt{i,n,begin,end}.o as well as libgcc.
- // These files are tied to a particular version of gcc.
- SmallString<128> CompilerSupportDir(GCCInstallation.getInstallPath());
- addPathIfExists(D, CompilerSupportDir, getFilePaths());
- }
- // libstd++ and libc++ must both be found in this one place.
- addPathIfExists(D, D.Dir + "/../sparc-myriad-rtems/lib", getFilePaths());
-}
-
-MyriadToolChain::~MyriadToolChain() {}
-
-void MyriadToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
- ArgStringList &CC1Args) const {
- if (!DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
- addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/include");
-}
-
-void MyriadToolChain::addLibCxxIncludePaths(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const {
- std::string Path(getDriver().getInstalledDir());
- addSystemInclude(DriverArgs, CC1Args, Path + "/../include/c++/v1");
-}
-
-void MyriadToolChain::addLibStdCxxIncludePaths(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const {
- StringRef LibDir = GCCInstallation.getParentLibPath();
- const GCCVersion &Version = GCCInstallation.getVersion();
- StringRef TripleStr = GCCInstallation.getTriple().str();
- const Multilib &Multilib = GCCInstallation.getMultilib();
- addLibStdCXXIncludePaths(
- LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text,
- TripleStr, Multilib.includeSuffix(), DriverArgs, CC1Args);
-}
-
-// MyriadToolChain handles several triples:
-// {shave,sparc{,el}}-myriad-{rtems,unknown}-elf
-Tool *MyriadToolChain::SelectTool(const JobAction &JA) const {
- // The inherited method works fine if not targeting the SHAVE.
- if (!isShaveCompilation(getTriple()))
- return ToolChain::SelectTool(JA);
- switch (JA.getKind()) {
- case Action::PreprocessJobClass:
- case Action::CompileJobClass:
- if (!Compiler)
- Compiler.reset(new tools::SHAVE::Compiler(*this));
- return Compiler.get();
- case Action::AssembleJobClass:
- if (!Assembler)
- Assembler.reset(new tools::SHAVE::Assembler(*this));
- return Assembler.get();
- default:
- return ToolChain::getTool(JA.getKind());
- }
-}
-
-Tool *MyriadToolChain::buildLinker() const {
- return new tools::Myriad::Linker(*this);
-}
-
-SanitizerMask MyriadToolChain::getSupportedSanitizers() const {
- return SanitizerKind::Address;
-}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Myriad.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Myriad.h
deleted file mode 100644
index cae574bdcfea..000000000000
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Myriad.h
+++ /dev/null
@@ -1,103 +0,0 @@
-//===--- Myriad.h - Myriad ToolChain Implementations ------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MYRIAD_H
-#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MYRIAD_H
-
-#include "Gnu.h"
-#include "clang/Driver/Tool.h"
-#include "clang/Driver/ToolChain.h"
-
-namespace clang {
-namespace driver {
-namespace tools {
-
-/// SHAVE tools -- Directly call moviCompile and moviAsm
-namespace SHAVE {
-class LLVM_LIBRARY_VISIBILITY Compiler : public Tool {
-public:
- Compiler(const ToolChain &TC) : Tool("moviCompile", "movicompile", TC) {}
-
- bool hasIntegratedCPP() 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 Assembler : public Tool {
-public:
- Assembler(const ToolChain &TC) : Tool("moviAsm", "moviAsm", TC) {}
-
- bool hasIntegratedCPP() const override { return false; } // not sure.
-
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
-};
-} // end namespace SHAVE
-
-/// The Myriad toolchain uses tools that are in two different namespaces.
-/// The Compiler and Assembler as defined above are in the SHAVE namespace,
-/// whereas the linker, which accepts code for a mixture of Sparc and SHAVE,
-/// is in the Myriad namespace.
-namespace Myriad {
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
-public:
- Linker(const ToolChain &TC) : Tool("shave::Linker", "ld", TC) {}
- bool hasIntegratedCPP() const override { return false; }
- bool isLinkJob() const override { return true; }
- void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &TCArgs,
- const char *LinkingOutput) const override;
-};
-} // end namespace Myriad
-} // end namespace tools
-
-namespace toolchains {
-
-/// MyriadToolChain - A tool chain using either clang or the external compiler
-/// installed by the Movidius SDK to perform all subcommands.
-class LLVM_LIBRARY_VISIBILITY MyriadToolChain : public Generic_ELF {
-public:
- MyriadToolChain(const Driver &D, const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args);
- ~MyriadToolChain() override;
-
- void
- AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
- void addLibCxxIncludePaths(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
- void addLibStdCxxIncludePaths(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
- Tool *SelectTool(const JobAction &JA) const override;
- unsigned GetDefaultDwarfVersion() const override { return 2; }
- SanitizerMask getSupportedSanitizers() const override;
-
-protected:
- Tool *buildLinker() const override;
- bool isShaveCompilation(const llvm::Triple &T) const {
- return T.getArch() == llvm::Triple::shave;
- }
-
-private:
- mutable std::unique_ptr<Tool> Compiler;
- mutable std::unique_ptr<Tool> Assembler;
-};
-
-} // end namespace toolchains
-} // end namespace driver
-} // end namespace clang
-
-#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MYRIAD_H
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/NaCl.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/NaCl.cpp
index 753459cb230b..22f038e5152f 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/NaCl.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/NaCl.cpp
@@ -31,8 +31,7 @@ void nacltools::AssemblerARM::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
- const toolchains::NaClToolChain &ToolChain =
- static_cast<const toolchains::NaClToolChain &>(getToolChain());
+ const auto &ToolChain = static_cast<const NaClToolChain &>(getToolChain());
InputInfo NaClMacros(types::TY_PP_Asm, ToolChain.GetNaClArmMacrosPath(),
"nacl-arm-macros.s");
InputInfoList NewInputs;
@@ -52,8 +51,7 @@ void nacltools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const ArgList &Args,
const char *LinkingOutput) const {
- const toolchains::NaClToolChain &ToolChain =
- static_cast<const toolchains::NaClToolChain &>(getToolChain());
+ const auto &ToolChain = static_cast<const NaClToolChain &>(getToolChain());
const Driver &D = ToolChain.getDriver();
const llvm::Triple::ArchType Arch = ToolChain.getArch();
const bool IsStatic =
@@ -120,8 +118,7 @@ void nacltools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
}
- Args.AddAllArgs(CmdArgs, options::OPT_L);
- Args.AddAllArgs(CmdArgs, options::OPT_u);
+ Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u});
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
@@ -308,6 +305,8 @@ void NaClToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
// if the value is libc++, and emits an error for other values.
GetCXXStdlibType(Args);
CmdArgs.push_back("-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
}
void NaClToolChain::addLibCxxIncludePaths(
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/NaCl.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/NaCl.h
index 5e5fdb583bb6..01d4719e7b92 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/NaCl.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/NaCl.h
@@ -27,7 +27,7 @@ public:
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
public:
Linker(const ToolChain &TC) : Tool("NaCl::Linker", "linker", TC) {}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/NetBSD.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/NetBSD.cpp
index 1ce5a2a203c2..240bf5764b9c 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/NetBSD.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/NetBSD.cpp
@@ -11,6 +11,7 @@
#include "Arch/Mips.h"
#include "Arch/Sparc.h"
#include "CommonArgs.h"
+#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Options.h"
@@ -29,12 +30,16 @@ void netbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
- claimNoWarnArgs(Args);
+ const auto &ToolChain = static_cast<const NetBSD &>(getToolChain());
+ const Driver &D = ToolChain.getDriver();
+ const llvm::Triple &Triple = ToolChain.getTriple();
ArgStringList CmdArgs;
+ claimNoWarnArgs(Args);
+
// 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,28 @@ 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: {
+ case llvm::Triple::sparc: {
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 +105,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));
@@ -113,27 +116,31 @@ void netbsd::Linker::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 auto &ToolChain = static_cast<const NetBSD &>(getToolChain());
const Driver &D = ToolChain.getDriver();
+ const llvm::Triple &Triple = ToolChain.getTriple();
+ const llvm::Triple::ArchType Arch = ToolChain.getArch();
+ const bool Static = Args.hasArg(options::OPT_static);
+ const bool Shared = Args.hasArg(options::OPT_shared);
+ const bool Pie = Args.hasArg(options::OPT_pie);
ArgStringList CmdArgs;
if (!D.SysRoot.empty())
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
CmdArgs.push_back("--eh-frame-hdr");
- if (Args.hasArg(options::OPT_static)) {
+ if (Static) {
CmdArgs.push_back("-Bstatic");
- if (Args.hasArg(options::OPT_pie)) {
+ if (Pie) {
Args.AddAllArgs(CmdArgs, options::OPT_pie);
CmdArgs.push_back("--no-dynamic-linker");
}
} else {
if (Args.hasArg(options::OPT_rdynamic))
CmdArgs.push_back("-export-dynamic");
- if (Args.hasArg(options::OPT_shared)) {
- CmdArgs.push_back("-Bshareable");
- } else {
+ if (Shared) {
+ CmdArgs.push_back("-shared");
+ } else if (!Args.hasArg(options::OPT_r)) {
Args.AddAllArgs(CmdArgs, options::OPT_pie);
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back("/libexec/ld.elf_so");
@@ -142,7 +149,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// Many NetBSD architectures support more than one ABI.
// Determine the correct emulation for ld.
- switch (ToolChain.getArch()) {
+ switch (Arch) {
case llvm::Triple::x86:
CmdArgs.push_back("-m");
CmdArgs.push_back("elf_i386");
@@ -150,7 +157,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 +175,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");
@@ -186,13 +193,13 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
case llvm::Triple::mips64el:
if (mips::hasMipsAbiArg(Args, "32")) {
CmdArgs.push_back("-m");
- if (ToolChain.getArch() == llvm::Triple::mips64)
+ if (Arch == llvm::Triple::mips64)
CmdArgs.push_back("elf32btsmip");
else
CmdArgs.push_back("elf32ltsmip");
} else if (mips::hasMipsAbiArg(Args, "64")) {
CmdArgs.push_back("-m");
- if (ToolChain.getArch() == llvm::Triple::mips64)
+ if (Arch == llvm::Triple::mips64)
CmdArgs.push_back("elf64btsmip");
else
CmdArgs.push_back("elf64ltsmip");
@@ -209,6 +216,16 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("elf64ppc");
break;
+ case llvm::Triple::riscv32:
+ CmdArgs.push_back("-m");
+ CmdArgs.push_back("elf32lriscv");
+ break;
+
+ case llvm::Triple::riscv64:
+ CmdArgs.push_back("-m");
+ CmdArgs.push_back("elf64lriscv");
+ break;
+
case llvm::Triple::sparc:
CmdArgs.push_back("-m");
CmdArgs.push_back("elf32_sparc");
@@ -223,94 +240,105 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
break;
}
+ if (Triple.isRISCV())
+ CmdArgs.push_back("-X");
+
+ assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- } else {
- assert(Output.isNothing() && "Invalid output.");
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
- if (!Args.hasArg(options::OPT_shared)) {
- CmdArgs.push_back(
- Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
- }
- CmdArgs.push_back(
- Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
- if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) {
- CmdArgs.push_back(
- Args.MakeArgString(ToolChain.GetFilePath("crtbeginS.o")));
- } else {
- CmdArgs.push_back(
- Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o")));
- }
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
+ const char *crt0 = nullptr;
+ const char *crtbegin = nullptr;
+ if (!Shared)
+ crt0 = "crt0.o";
+
+ if (Shared || Pie)
+ crtbegin = "crtbeginS.o";
+ else
+ crtbegin = "crtbegin.o";
+
+ if (crt0)
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt0)));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
}
- Args.AddAllArgs(CmdArgs, options::OPT_L);
- Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
- Args.AddAllArgs(CmdArgs, options::OPT_e);
- Args.AddAllArgs(CmdArgs, options::OPT_s);
- Args.AddAllArgs(CmdArgs, options::OPT_t);
- Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
- Args.AddAllArgs(CmdArgs, options::OPT_r);
+ Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
+ options::OPT_s, options::OPT_t, options::OPT_r});
+ ToolChain.AddFilePathLibArgs(Args, CmdArgs);
- 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);
bool useLibgcc = true;
- if (Major >= 7 || Major == 0) {
- switch (ToolChain.getArch()) {
- case llvm::Triple::aarch64:
- case llvm::Triple::aarch64_be:
- case llvm::Triple::arm:
- case llvm::Triple::armeb:
- case llvm::Triple::thumb:
- case llvm::Triple::thumbeb:
- case llvm::Triple::ppc:
- case llvm::Triple::ppc64:
- case llvm::Triple::ppc64le:
- case llvm::Triple::sparc:
- case llvm::Triple::sparcv9:
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- useLibgcc = false;
- break;
- default:
- break;
- }
+ switch (ToolChain.getArch()) {
+ case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_be:
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ case llvm::Triple::sparc:
+ case llvm::Triple::sparcv9:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ useLibgcc = false;
+ break;
+ default:
+ break;
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
+ options::OPT_r)) {
// Use the static OpenMP runtime with -static-openmp
- bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) &&
- !Args.hasArg(options::OPT_static);
- addOpenMPRuntime(CmdArgs, getToolChain(), Args, StaticOpenMP);
+ bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Static;
+ addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP);
if (D.CCCIsCXX()) {
if (ToolChain.ShouldLinkCXXStdlib(Args))
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lm");
}
+
+ // Silence warnings when linking C code with a C++ '-stdlib' argument.
+ Args.ClaimAllArgs(options::OPT_stdlib_EQ);
+
+ // Additional linker set-up and flags for Fortran. This is required in order
+ // to generate executables. As Fortran runtime depends on the C runtime,
+ // these dependencies need to be listed before the C runtime below (i.e.
+ // AddRunTimeLibs).
+ if (D.IsFlangMode()) {
+ addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
+ addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
+ CmdArgs.push_back("-lm");
+ }
+
if (NeedsSanitizerDeps)
- linkSanitizerRuntimeDeps(getToolChain(), CmdArgs);
+ linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs);
if (NeedsXRayDeps)
- linkXRayRuntimeDeps(ToolChain, CmdArgs);
+ linkXRayRuntimeDeps(ToolChain, Args, CmdArgs);
if (Args.hasArg(options::OPT_pthread))
CmdArgs.push_back("-lpthread");
CmdArgs.push_back("-lc");
if (useLibgcc) {
- if (Args.hasArg(options::OPT_static)) {
+ if (Static) {
// libgcc_eh depends on libc, so resolve as much as possible,
// pull in any new requirements from libc and then get the rest
// of libgcc.
@@ -326,13 +354,15 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
- if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
- CmdArgs.push_back(
- Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
+ const char *crtend = nullptr;
+ if (Shared || Pie)
+ crtend = "crtendS.o";
else
- CmdArgs.push_back(
- Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
+ crtend = "crtend.o";
+
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
}
@@ -356,7 +386,7 @@ NetBSD::NetBSD(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// what all logic is needed to emulate the '=' prefix here.
switch (Triple.getArch()) {
case llvm::Triple::x86:
- getFilePaths().push_back("=/usr/lib/i386");
+ getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib/i386"));
break;
case llvm::Triple::arm:
case llvm::Triple::armeb:
@@ -365,35 +395,35 @@ NetBSD::NetBSD(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
switch (Triple.getEnvironment()) {
case llvm::Triple::EABI:
case llvm::Triple::GNUEABI:
- getFilePaths().push_back("=/usr/lib/eabi");
+ getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib/eabi"));
break;
case llvm::Triple::EABIHF:
case llvm::Triple::GNUEABIHF:
- getFilePaths().push_back("=/usr/lib/eabihf");
+ getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib/eabihf"));
break;
default:
- getFilePaths().push_back("=/usr/lib/oabi");
+ getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib/oabi"));
break;
}
break;
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
if (tools::mips::hasMipsAbiArg(Args, "o32"))
- getFilePaths().push_back("=/usr/lib/o32");
+ getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib/o32"));
else if (tools::mips::hasMipsAbiArg(Args, "64"))
- getFilePaths().push_back("=/usr/lib/64");
+ getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib/64"));
break;
case llvm::Triple::ppc:
- getFilePaths().push_back("=/usr/lib/powerpc");
+ getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib/powerpc"));
break;
case llvm::Triple::sparc:
- getFilePaths().push_back("=/usr/lib/sparc");
+ getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib/sparc"));
break;
default:
break;
}
- getFilePaths().push_back("=/usr/lib");
+ getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib"));
}
}
@@ -404,40 +434,72 @@ Tool *NetBSD::buildAssembler() const {
Tool *NetBSD::buildLinker() const { return new tools::netbsd::Linker(*this); }
ToolChain::CXXStdlibType NetBSD::GetDefaultCXXStdlibType() const {
- unsigned Major, Minor, Micro;
- getTriple().getOSVersion(Major, Minor, Micro);
- if (Major >= 7 || Major == 0) {
- switch (getArch()) {
- case llvm::Triple::aarch64:
- case llvm::Triple::aarch64_be:
- case llvm::Triple::arm:
- case llvm::Triple::armeb:
- case llvm::Triple::thumb:
- case llvm::Triple::thumbeb:
- case llvm::Triple::ppc:
- case llvm::Triple::ppc64:
- case llvm::Triple::ppc64le:
- case llvm::Triple::sparc:
- case llvm::Triple::sparcv9:
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- return ToolChain::CST_Libcxx;
- default:
- break;
- }
+ switch (getArch()) {
+ case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_be:
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ case llvm::Triple::sparc:
+ case llvm::Triple::sparcv9:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ return ToolChain::CST_Libcxx;
+ default:
+ break;
}
return ToolChain::CST_Libstdcxx;
}
+void NetBSD::AddClangSystemIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ const Driver &D = getDriver();
+
+ if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
+ return;
+
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+ SmallString<128> Dir(D.ResourceDir);
+ llvm::sys::path::append(Dir, "include");
+ addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ }
+
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+
+ // Check for configure-time C include directories.
+ StringRef CIncludeDirs(C_INCLUDE_DIRS);
+ if (CIncludeDirs != "") {
+ SmallVector<StringRef, 5> dirs;
+ CIncludeDirs.split(dirs, ":");
+ for (StringRef dir : dirs) {
+ StringRef Prefix =
+ llvm::sys::path::is_absolute(dir) ? StringRef(D.SysRoot) : "";
+ addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
+ }
+ return;
+ }
+
+ addExternCSystemInclude(DriverArgs, CC1Args,
+ concat(D.SysRoot, "/usr/include"));
+}
+
void NetBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
const std::string Candidates[] = {
// directory relative to build tree
- getDriver().Dir + "/../include/c++/v1",
+ concat(getDriver().Dir, "/../include/c++/v1"),
// system install with full upstream path
- getDriver().SysRoot + "/usr/include/c++/v1",
+ concat(getDriver().SysRoot, "/usr/include/c++/v1"),
// system install from src
- getDriver().SysRoot + "/usr/include/c++",
+ concat(getDriver().SysRoot, "/usr/include/c++"),
};
for (const auto &IncludePath : Candidates) {
@@ -452,7 +514,7 @@ void NetBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
void NetBSD::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
- addLibStdCXXIncludePaths(getDriver().SysRoot + "/usr/include/g++", "", "",
+ addLibStdCXXIncludePaths(concat(getDriver().SysRoot, "/usr/include/g++"), "", "",
DriverArgs, CC1Args);
}
@@ -473,7 +535,6 @@ SanitizerMask NetBSD::getSupportedSanitizers() const {
Res |= SanitizerKind::Address;
Res |= SanitizerKind::PointerCompare;
Res |= SanitizerKind::PointerSubtract;
- Res |= SanitizerKind::Function;
Res |= SanitizerKind::Leak;
Res |= SanitizerKind::SafeStack;
Res |= SanitizerKind::Scudo;
@@ -496,18 +557,19 @@ 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");
- unsigned Major, Minor, Micro;
- getTriple().getOSVersion(Major, Minor, Micro);
+ VersionTuple OsVersion = getTriple().getOSVersion();
bool UseInitArrayDefault =
- Major >= 9 || Major == 0 ||
- getTriple().getArch() == llvm::Triple::aarch64 ||
- getTriple().getArch() == llvm::Triple::aarch64_be ||
- getTriple().getArch() == llvm::Triple::arm ||
- getTriple().getArch() == llvm::Triple::armeb;
+ OsVersion >= VersionTuple(9) || OsVersion.getMajor() == 0 ||
+ getTriple().getArch() == llvm::Triple::aarch64 ||
+ getTriple().getArch() == llvm::Triple::aarch64_be ||
+ getTriple().getArch() == llvm::Triple::arm ||
+ getTriple().getArch() == llvm::Triple::armeb ||
+ getTriple().getArch() == llvm::Triple::riscv32 ||
+ getTriple().getArch() == llvm::Triple::riscv64;
if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
options::OPT_fno_use_init_array, UseInitArrayDefault))
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/NetBSD.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/NetBSD.h
index 8348554fd149..96303acaa009 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/NetBSD.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/NetBSD.h
@@ -17,9 +17,9 @@ namespace clang {
namespace driver {
namespace tools {
-/// netbsd -- Directly call GNU Binutils assembler and linker
+/// Directly call GNU Binutils assembler and linker
namespace netbsd {
-class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
+class LLVM_LIBRARY_VISIBILITY Assembler final : public Tool {
public:
Assembler(const ToolChain &TC) : Tool("netbsd::Assembler", "assembler", TC) {}
@@ -31,7 +31,7 @@ public:
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
public:
Linker(const ToolChain &TC) : Tool("netbsd::Linker", "linker", TC) {}
@@ -58,6 +58,9 @@ public:
CXXStdlibType GetDefaultCXXStdlibType() const override;
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
void addLibCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
@@ -65,8 +68,9 @@ public:
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override {
- return true;
+ UnwindTableLevel
+ getDefaultUnwindTableLevel(const llvm::opt::ArgList &Args) const override {
+ return UnwindTableLevel::Asynchronous;
}
llvm::ExceptionHandling GetExceptionModel(
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/OHOS.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/OHOS.cpp
new file mode 100644
index 000000000000..1e50c9d71d59
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/OHOS.cpp
@@ -0,0 +1,419 @@
+//===--- OHOS.cpp - OHOS ToolChain Implementations --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "OHOS.h"
+#include "Arch/ARM.h"
+#include "CommonArgs.h"
+#include "clang/Config/config.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "clang/Driver/SanitizerArgs.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/ProfileData/InstrProf.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+using namespace clang::driver::tools::arm;
+
+using tools::addMultilibFlag;
+using tools::addPathIfExists;
+
+static bool findOHOSMuslMultilibs(const Multilib::flags_list &Flags,
+ DetectedMultilibs &Result) {
+ MultilibSet Multilibs;
+ Multilibs.push_back(Multilib());
+ // -mcpu=cortex-a7
+ // -mfloat-abi=soft -mfloat-abi=softfp -mfloat-abi=hard
+ // -mfpu=neon-vfpv4
+ Multilibs.push_back(
+ Multilib("/a7_soft", {}, {}, {"-mcpu=cortex-a7", "-mfloat-abi=soft"}));
+
+ Multilibs.push_back(
+ Multilib("/a7_softfp_neon-vfpv4", {}, {},
+ {"-mcpu=cortex-a7", "-mfloat-abi=softfp", "-mfpu=neon-vfpv4"}));
+
+ Multilibs.push_back(
+ Multilib("/a7_hard_neon-vfpv4", {}, {},
+ {"-mcpu=cortex-a7", "-mfloat-abi=hard", "-mfpu=neon-vfpv4"}));
+
+ if (Multilibs.select(Flags, Result.SelectedMultilibs)) {
+ Result.Multilibs = Multilibs;
+ return true;
+ }
+ return false;
+}
+
+static bool findOHOSMultilibs(const Driver &D,
+ const ToolChain &TC,
+ const llvm::Triple &TargetTriple,
+ StringRef Path, const ArgList &Args,
+ DetectedMultilibs &Result) {
+ Multilib::flags_list Flags;
+ bool IsA7 = false;
+ if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
+ IsA7 = A->getValue() == StringRef("cortex-a7");
+ addMultilibFlag(IsA7, "-mcpu=cortex-a7", Flags);
+
+ bool IsMFPU = false;
+ if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ))
+ IsMFPU = A->getValue() == StringRef("neon-vfpv4");
+ addMultilibFlag(IsMFPU, "-mfpu=neon-vfpv4", Flags);
+
+ tools::arm::FloatABI ARMFloatABI = getARMFloatABI(D, TargetTriple, Args);
+ addMultilibFlag((ARMFloatABI == tools::arm::FloatABI::Soft),
+ "-mfloat-abi=soft", Flags);
+ addMultilibFlag((ARMFloatABI == tools::arm::FloatABI::SoftFP),
+ "-mfloat-abi=softfp", Flags);
+ addMultilibFlag((ARMFloatABI == tools::arm::FloatABI::Hard),
+ "-mfloat-abi=hard", Flags);
+
+ return findOHOSMuslMultilibs(Flags, Result);
+}
+
+std::string OHOS::getMultiarchTriple(const llvm::Triple &T) const {
+ // For most architectures, just use whatever we have rather than trying to be
+ // clever.
+ switch (T.getArch()) {
+ default:
+ break;
+
+ // We use the existence of '/lib/<triple>' as a directory to detect some
+ // common linux triples that don't quite match the Clang triple for both
+ // 32-bit and 64-bit targets. Multiarch fixes its install triples to these
+ // regardless of what the actual target triple is.
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ return T.isOSLiteOS() ? "arm-liteos-ohos" : "arm-linux-ohos";
+ case llvm::Triple::riscv32:
+ return "riscv32-linux-ohos";
+ case llvm::Triple::riscv64:
+ return "riscv64-linux-ohos";
+ case llvm::Triple::mipsel:
+ return "mipsel-linux-ohos";
+ case llvm::Triple::x86:
+ return "i686-linux-ohos";
+ case llvm::Triple::x86_64:
+ return "x86_64-linux-ohos";
+ case llvm::Triple::aarch64:
+ return "aarch64-linux-ohos";
+ }
+ return T.str();
+}
+
+std::string OHOS::getMultiarchTriple(const Driver &D,
+ const llvm::Triple &TargetTriple,
+ StringRef SysRoot) const {
+ return getMultiarchTriple(TargetTriple);
+}
+
+static std::string makePath(const std::initializer_list<std::string> &IL) {
+ SmallString<128> P;
+ for (const auto &S : IL)
+ llvm::sys::path::append(P, S);
+ return static_cast<std::string>(P.str());
+}
+
+/// OHOS Toolchain
+OHOS::OHOS(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
+ std::string SysRoot = computeSysRoot();
+
+ // Select the correct multilib according to the given arguments.
+ DetectedMultilibs Result;
+ findOHOSMultilibs(D, *this, Triple, "", Args, Result);
+ Multilibs = Result.Multilibs;
+ SelectedMultilibs = Result.SelectedMultilibs;
+ if (!SelectedMultilibs.empty()) {
+ SelectedMultilib = SelectedMultilibs.back();
+ }
+
+ getFilePaths().clear();
+ for (const auto &CandidateLibPath : getArchSpecificLibPaths())
+ if (getVFS().exists(CandidateLibPath))
+ getFilePaths().push_back(CandidateLibPath);
+
+ getLibraryPaths().clear();
+ for (auto &Path : getRuntimePaths())
+ if (getVFS().exists(Path))
+ getLibraryPaths().push_back(Path);
+
+ // OHOS sysroots contain a library directory for each supported OS
+ // version as well as some unversioned libraries in the usual multiarch
+ // directory. Support --target=aarch64-linux-ohosX.Y.Z or
+ // --target=aarch64-linux-ohosX.Y or --target=aarch64-linux-ohosX
+ path_list &Paths = getFilePaths();
+ std::string SysRootLibPath = makePath({SysRoot, "usr", "lib"});
+ std::string MultiarchTriple = getMultiarchTriple(getTriple());
+ addPathIfExists(D, makePath({SysRootLibPath, SelectedMultilib.gccSuffix()}),
+ Paths);
+ addPathIfExists(D,
+ makePath({D.Dir, "..", "lib", MultiarchTriple,
+ SelectedMultilib.gccSuffix()}),
+ Paths);
+
+ addPathIfExists(
+ D,
+ makePath({SysRootLibPath, MultiarchTriple, SelectedMultilib.gccSuffix()}),
+ Paths);
+}
+
+ToolChain::RuntimeLibType OHOS::GetRuntimeLibType(
+ const ArgList &Args) const {
+ if (Arg *A = Args.getLastArg(clang::driver::options::OPT_rtlib_EQ)) {
+ StringRef Value = A->getValue();
+ if (Value != "compiler-rt")
+ getDriver().Diag(clang::diag::err_drv_invalid_rtlib_name)
+ << A->getAsString(Args);
+ }
+
+ return ToolChain::RLT_CompilerRT;
+}
+
+ToolChain::CXXStdlibType
+OHOS::GetCXXStdlibType(const ArgList &Args) const {
+ if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
+ StringRef Value = A->getValue();
+ if (Value != "libc++")
+ getDriver().Diag(diag::err_drv_invalid_stdlib_name)
+ << A->getAsString(Args);
+ }
+
+ return ToolChain::CST_Libcxx;
+}
+
+void OHOS::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ const Driver &D = getDriver();
+ const llvm::Triple &Triple = getTriple();
+ std::string SysRoot = computeSysRoot();
+
+ if (DriverArgs.hasArg(options::OPT_nostdinc))
+ return;
+
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+ SmallString<128> P(D.ResourceDir);
+ llvm::sys::path::append(P, "include");
+ addSystemInclude(DriverArgs, CC1Args, P);
+ }
+
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+
+ // Check for configure-time C include directories.
+ StringRef CIncludeDirs(C_INCLUDE_DIRS);
+ if (CIncludeDirs != "") {
+ SmallVector<StringRef, 5> dirs;
+ CIncludeDirs.split(dirs, ":");
+ for (StringRef dir : dirs) {
+ StringRef Prefix =
+ llvm::sys::path::is_absolute(dir) ? StringRef(SysRoot) : "";
+ addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
+ }
+ return;
+ }
+
+ addExternCSystemInclude(DriverArgs, CC1Args,
+ SysRoot + "/usr/include/" +
+ getMultiarchTriple(Triple));
+ addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include");
+ addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
+}
+
+void OHOS::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
+ DriverArgs.hasArg(options::OPT_nostdincxx))
+ return;
+
+ switch (GetCXXStdlibType(DriverArgs)) {
+ case ToolChain::CST_Libcxx: {
+ std::string IncPath = makePath({getDriver().Dir, "..", "include"});
+ std::string IncTargetPath =
+ makePath({IncPath, getMultiarchTriple(getTriple()), "c++", "v1"});
+ if (getVFS().exists(IncTargetPath)) {
+ addSystemInclude(DriverArgs, CC1Args, makePath({IncPath, "c++", "v1"}));
+ addSystemInclude(DriverArgs, CC1Args, IncTargetPath);
+ }
+ break;
+ }
+
+ default:
+ llvm_unreachable("invalid stdlib name");
+ }
+}
+
+void OHOS::AddCXXStdlibLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ switch (GetCXXStdlibType(Args)) {
+ case ToolChain::CST_Libcxx:
+ CmdArgs.push_back("-lc++");
+ CmdArgs.push_back("-lc++abi");
+ CmdArgs.push_back("-lunwind");
+ break;
+
+ case ToolChain::CST_Libstdcxx:
+ llvm_unreachable("invalid stdlib name");
+ }
+}
+
+std::string OHOS::computeSysRoot() const {
+ std::string SysRoot =
+ !getDriver().SysRoot.empty()
+ ? getDriver().SysRoot
+ : makePath({getDriver().getInstalledDir(), "..", "..", "sysroot"});
+ if (!llvm::sys::fs::exists(SysRoot))
+ return std::string();
+
+ std::string ArchRoot = makePath({SysRoot, getMultiarchTriple(getTriple())});
+ return llvm::sys::fs::exists(ArchRoot) ? ArchRoot : SysRoot;
+}
+
+ToolChain::path_list OHOS::getRuntimePaths() const {
+ SmallString<128> P;
+ path_list Paths;
+ const Driver &D = getDriver();
+ const llvm::Triple &Triple = getTriple();
+
+ // First try the triple passed to driver as --target=<triple>.
+ P.assign(D.ResourceDir);
+ llvm::sys::path::append(P, "lib", D.getTargetTriple(), SelectedMultilib.gccSuffix());
+ Paths.push_back(P.c_str());
+
+ // Second try the normalized triple.
+ P.assign(D.ResourceDir);
+ llvm::sys::path::append(P, "lib", Triple.str(), SelectedMultilib.gccSuffix());
+ Paths.push_back(P.c_str());
+
+ // Third try the effective triple.
+ P.assign(D.ResourceDir);
+ std::string SysRoot = computeSysRoot();
+ llvm::sys::path::append(P, "lib", getMultiarchTriple(Triple),
+ SelectedMultilib.gccSuffix());
+ Paths.push_back(P.c_str());
+
+ return Paths;
+}
+
+std::string OHOS::getDynamicLinker(const ArgList &Args) const {
+ const llvm::Triple &Triple = getTriple();
+ const llvm::Triple::ArchType Arch = getArch();
+
+ assert(Triple.isMusl());
+ std::string ArchName;
+ bool IsArm = false;
+
+ switch (Arch) {
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ ArchName = "arm";
+ IsArm = true;
+ break;
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumbeb:
+ ArchName = "armeb";
+ IsArm = true;
+ break;
+ default:
+ ArchName = Triple.getArchName().str();
+ }
+ if (IsArm &&
+ (tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard))
+ ArchName += "hf";
+
+ return "/lib/ld-musl-" + ArchName + ".so.1";
+}
+
+std::string OHOS::getCompilerRT(const ArgList &Args, StringRef Component,
+ FileType Type) const {
+ SmallString<128> Path(getDriver().ResourceDir);
+ llvm::sys::path::append(Path, "lib", getMultiarchTriple(getTriple()),
+ SelectedMultilib.gccSuffix());
+ const char *Prefix =
+ Type == ToolChain::FT_Object ? "" : "lib";
+ const char *Suffix;
+ switch (Type) {
+ case ToolChain::FT_Object:
+ Suffix = ".o";
+ break;
+ case ToolChain::FT_Static:
+ Suffix = ".a";
+ break;
+ case ToolChain::FT_Shared:
+ Suffix = ".so";
+ break;
+ }
+ llvm::sys::path::append(
+ Path, Prefix + Twine("clang_rt.") + Component + Suffix);
+ return static_cast<std::string>(Path.str());
+}
+
+void OHOS::addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const {
+ CmdArgs.push_back("-z");
+ CmdArgs.push_back("now");
+ CmdArgs.push_back("-z");
+ CmdArgs.push_back("relro");
+ CmdArgs.push_back("-z");
+ CmdArgs.push_back("max-page-size=4096");
+ // .gnu.hash section is not compatible with the MIPS target
+ if (getArch() != llvm::Triple::mipsel)
+ CmdArgs.push_back("--hash-style=both");
+#ifdef ENABLE_LINKER_BUILD_ID
+ CmdArgs.push_back("--build-id");
+#endif
+ CmdArgs.push_back("--enable-new-dtags");
+}
+
+SanitizerMask OHOS::getSupportedSanitizers() const {
+ SanitizerMask Res = ToolChain::getSupportedSanitizers();
+ Res |= SanitizerKind::Address;
+ Res |= SanitizerKind::PointerCompare;
+ Res |= SanitizerKind::PointerSubtract;
+ Res |= SanitizerKind::Fuzzer;
+ Res |= SanitizerKind::FuzzerNoLink;
+ Res |= SanitizerKind::Memory;
+ Res |= SanitizerKind::Vptr;
+ Res |= SanitizerKind::SafeStack;
+ Res |= SanitizerKind::Scudo;
+ // TODO: kASAN for liteos ??
+ // TODO: Support TSAN and HWASAN and update mask.
+ return Res;
+}
+
+// TODO: Make a base class for Linux and OHOS and move this there.
+void OHOS::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);
+}
+
+ToolChain::path_list OHOS::getArchSpecificLibPaths() const {
+ ToolChain::path_list Paths;
+ llvm::Triple Triple = getTriple();
+ Paths.push_back(
+ makePath({getDriver().ResourceDir, "lib", getMultiarchTriple(Triple)}));
+ return Paths;
+}
+
+ToolChain::UnwindLibType OHOS::GetUnwindLibType(const llvm::opt::ArgList &Args) const {
+ if (Args.getLastArg(options::OPT_unwindlib_EQ))
+ return Generic_ELF::GetUnwindLibType(Args);
+ return GetDefaultUnwindLibType();
+}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/OHOS.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/OHOS.h
new file mode 100644
index 000000000000..2a380420922d
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/OHOS.h
@@ -0,0 +1,95 @@
+//===--- OHOS.h - OHOS ToolChain Implementations ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_OHOS_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_OHOS_H
+
+#include "Linux.h"
+#include "clang/Driver/Tool.h"
+#include "clang/Driver/ToolChain.h"
+
+namespace clang {
+namespace driver {
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY OHOS : public Generic_ELF {
+public:
+ OHOS(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ bool HasNativeLLVMSupport() const override { return true; }
+
+ bool IsMathErrnoDefault() const override { return false; }
+
+ RuntimeLibType GetDefaultRuntimeLibType() const override {
+ return ToolChain::RLT_CompilerRT;
+ }
+ CXXStdlibType GetDefaultCXXStdlibType() const override {
+ return ToolChain::CST_Libcxx;
+ }
+ // Not add -funwind-tables by default
+ bool isPICDefault() const override { return false; }
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override { return true; }
+ bool isPICDefaultForced() const override { return false; }
+ UnwindLibType GetUnwindLibType(const llvm::opt::ArgList &Args) const override;
+ UnwindLibType GetDefaultUnwindLibType() const override { return UNW_CompilerRT; }
+
+ RuntimeLibType
+ GetRuntimeLibType(const llvm::opt::ArgList &Args) const override;
+ CXXStdlibType
+ GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
+
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void
+ AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+
+ std::string computeSysRoot() const override;
+ std::string getDynamicLinker(const llvm::opt::ArgList &Args) const override;
+
+ std::string
+ getCompilerRT(const llvm::opt::ArgList &Args, StringRef Component,
+ FileType Type = ToolChain::FT_Static) const override;
+
+ const char *getDefaultLinker() const override {
+ return "ld.lld";
+ }
+
+ Tool *buildLinker() const override {
+ return new tools::gnutools::Linker(*this);
+ }
+ Tool *buildAssembler() const override {
+ return new tools::gnutools::Assembler(*this);
+ }
+
+ path_list getRuntimePaths() const;
+
+protected:
+ std::string getMultiarchTriple(const llvm::Triple &T) const;
+ std::string getMultiarchTriple(const Driver &D,
+ const llvm::Triple &TargetTriple,
+ StringRef SysRoot) const override;
+ void addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const override;
+ SanitizerMask getSupportedSanitizers() const override;
+ void addProfileRTLibs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+ path_list getArchSpecificLibPaths() const override;
+
+private:
+ Multilib SelectedMultilib;
+};
+
+} // end namespace toolchains
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_OHOS_H
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/OpenBSD.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/OpenBSD.cpp
index 89828fbb6f5f..fd6aa4d7e684 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/OpenBSD.cpp
+++ b/contrib/llvm-project/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"
@@ -16,6 +17,7 @@
#include "clang/Driver/SanitizerArgs.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/VirtualFileSystem.h"
using namespace clang::driver;
using namespace clang::driver::tools;
@@ -28,16 +30,28 @@ void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
- claimNoWarnArgs(Args);
+ const auto &ToolChain = static_cast<const OpenBSD &>(getToolChain());
+ const Driver &D = ToolChain.getDriver();
+ const llvm::Triple &Triple = ToolChain.getTriple();
ArgStringList CmdArgs;
- switch (getToolChain().getArch()) {
+ claimNoWarnArgs(Args);
+
+ 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: {
+ 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 +59,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 +69,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 +98,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));
@@ -92,9 +109,15 @@ void openbsd::Linker::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 = getToolChain().getDriver();
+ const auto &ToolChain = static_cast<const OpenBSD &>(getToolChain());
+ const Driver &D = ToolChain.getDriver();
+ const llvm::Triple::ArchType Arch = ToolChain.getArch();
+ const bool Static = Args.hasArg(options::OPT_static);
+ const bool Shared = Args.hasArg(options::OPT_shared);
+ const bool Profiling = Args.hasArg(options::OPT_pg);
+ const bool Pie = Args.hasArg(options::OPT_pie);
+ const bool Nopie = Args.hasArg(options::OPT_no_pie, options::OPT_nopie);
+ const bool Relocatable = Args.hasArg(options::OPT_r);
ArgStringList CmdArgs;
// Silence warning for "clang -g foo.o -o foo"
@@ -105,51 +128,55 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// handled somewhere else.
Args.ClaimAllArgs(options::OPT_w);
- if (ToolChain.getArch() == llvm::Triple::mips64)
+ if (!D.SysRoot.empty())
+ CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+
+ if (Arch == llvm::Triple::mips64)
CmdArgs.push_back("-EB");
- else if (ToolChain.getArch() == llvm::Triple::mips64el)
+ else if (Arch == llvm::Triple::mips64el)
CmdArgs.push_back("-EL");
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) {
+ if (!Args.hasArg(options::OPT_nostdlib) && !Shared && !Relocatable) {
CmdArgs.push_back("-e");
CmdArgs.push_back("__start");
}
CmdArgs.push_back("--eh-frame-hdr");
- if (Args.hasArg(options::OPT_static)) {
+ if (Static) {
CmdArgs.push_back("-Bstatic");
} else {
if (Args.hasArg(options::OPT_rdynamic))
CmdArgs.push_back("-export-dynamic");
- CmdArgs.push_back("-Bdynamic");
- if (Args.hasArg(options::OPT_shared)) {
+ if (Shared) {
CmdArgs.push_back("-shared");
- } else {
+ } else if (!Relocatable) {
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back("/usr/libexec/ld.so");
}
}
- if (Args.hasArg(options::OPT_pie))
+ if (Pie)
CmdArgs.push_back("-pie");
- if (Args.hasArg(options::OPT_nopie) || Args.hasArg(options::OPT_pg))
+ if (Nopie || Profiling)
CmdArgs.push_back("-nopie");
+ if (Arch == llvm::Triple::riscv64)
+ CmdArgs.push_back("-X");
+
+ assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- } else {
- assert(Output.isNothing() && "Invalid output.");
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
const char *crt0 = nullptr;
const char *crtbegin = nullptr;
- if (!Args.hasArg(options::OPT_shared)) {
- if (Args.hasArg(options::OPT_pg))
+ if (!Shared) {
+ if (Profiling)
crt0 = "gcrt0.o";
- else if (Args.hasArg(options::OPT_static) &&
- !Args.hasArg(options::OPT_nopie))
+ else if (Static && !Nopie)
crt0 = "rcrt0.o";
else
crt0 = "crt0.o";
@@ -165,49 +192,79 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_L);
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
- Args.AddAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_e,
- options::OPT_s, options::OPT_t,
- options::OPT_Z_Flag, options::OPT_r});
+ Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s,
+ options::OPT_t, options::OPT_r});
+
+ if (D.isUsingLTO()) {
+ assert(!Inputs.empty() && "Must have at least one input.");
+ // Find the first filename InputInfo object.
+ auto Input = llvm::find_if(
+ Inputs, [](const InputInfo &II) -> bool { return II.isFilename(); });
+ if (Input == Inputs.end())
+ // For a very rare case, all of the inputs to the linker are
+ // InputArg. If that happens, just use the first InputInfo.
+ Input = Inputs.begin();
+
+ addLTOOptions(ToolChain, Args, CmdArgs, Output, *Input,
+ D.getLTOMode() == LTOK_Thin);
+ }
bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
+ options::OPT_r)) {
// Use the static OpenMP runtime with -static-openmp
- bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) &&
- !Args.hasArg(options::OPT_static);
+ bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Static;
addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP);
if (D.CCCIsCXX()) {
if (ToolChain.ShouldLinkCXXStdlib(Args))
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
- if (Args.hasArg(options::OPT_pg))
+ if (Profiling)
CmdArgs.push_back("-lm_p");
else
CmdArgs.push_back("-lm");
}
+
+ // Silence warnings when linking C code with a C++ '-stdlib' argument.
+ Args.ClaimAllArgs(options::OPT_stdlib_EQ);
+
+ // Additional linker set-up and flags for Fortran. This is required in order
+ // to generate executables. As Fortran runtime depends on the C runtime,
+ // these dependencies need to be listed before the C runtime below (i.e.
+ // AddRunTimeLibs).
+ if (D.IsFlangMode()) {
+ addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
+ addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
+ if (Profiling)
+ CmdArgs.push_back("-lm_p");
+ else
+ CmdArgs.push_back("-lm");
+ }
+
if (NeedsSanitizerDeps) {
CmdArgs.push_back(ToolChain.getCompilerRTArgString(Args, "builtins"));
- linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
+ linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs);
}
if (NeedsXRayDeps) {
CmdArgs.push_back(ToolChain.getCompilerRTArgString(Args, "builtins"));
- linkXRayRuntimeDeps(ToolChain, CmdArgs);
+ linkXRayRuntimeDeps(ToolChain, Args, CmdArgs);
}
// FIXME: For some reason GCC passes -lgcc before adding
// the default system libraries. Just mimic this for now.
CmdArgs.push_back("-lcompiler_rt");
if (Args.hasArg(options::OPT_pthread)) {
- if (!Args.hasArg(options::OPT_shared) && Args.hasArg(options::OPT_pg))
+ if (!Shared && Profiling)
CmdArgs.push_back("-lpthread_p");
else
CmdArgs.push_back("-lpthread");
}
- if (!Args.hasArg(options::OPT_shared)) {
- if (Args.hasArg(options::OPT_pg))
+ if (!Shared) {
+ if (Profiling)
CmdArgs.push_back("-lc_p");
else
CmdArgs.push_back("-lc");
@@ -216,9 +273,10 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lcompiler_rt");
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
const char *crtend = nullptr;
- if (!Args.hasArg(options::OPT_shared))
+ if (!Shared)
crtend = "crtend.o";
else
crtend = "crtendS.o";
@@ -237,16 +295,15 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
SanitizerMask OpenBSD::getSupportedSanitizers() const {
const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
-
- // For future use, only UBsan at the moment
SanitizerMask Res = ToolChain::getSupportedSanitizers();
-
if (IsX86 || IsX86_64) {
Res |= SanitizerKind::Vptr;
Res |= SanitizerKind::Fuzzer;
Res |= SanitizerKind::FuzzerNoLink;
}
-
+ if (IsX86_64) {
+ Res |= SanitizerKind::KernelAddress;
+ }
return Res;
}
@@ -255,7 +312,7 @@ SanitizerMask OpenBSD::getSupportedSanitizers() const {
OpenBSD::OpenBSD(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
- getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
+ getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib"));
}
void OpenBSD::AddClangSystemIncludeArgs(
@@ -288,13 +345,14 @@ void OpenBSD::AddClangSystemIncludeArgs(
return;
}
- addExternCSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/usr/include");
+ addExternCSystemInclude(DriverArgs, CC1Args,
+ concat(D.SysRoot, "/usr/include"));
}
void OpenBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/usr/include/c++/v1");
+ concat(getDriver().SysRoot, "/usr/include/c++/v1"));
}
void OpenBSD::AddCXXStdlibLibArgs(const ArgList &Args,
@@ -302,16 +360,27 @@ void OpenBSD::AddCXXStdlibLibArgs(const ArgList &Args,
bool Profiling = Args.hasArg(options::OPT_pg);
CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back(Profiling ? "-lc++abi_p" : "-lc++abi");
CmdArgs.push_back(Profiling ? "-lpthread_p" : "-lpthread");
}
-std::string OpenBSD::getCompilerRT(const ArgList &Args,
- StringRef Component,
+std::string OpenBSD::getCompilerRT(const ArgList &Args, StringRef Component,
FileType Type) const {
- SmallString<128> Path(getDriver().SysRoot);
- llvm::sys::path::append(Path, "/usr/lib/libcompiler_rt.a");
- return std::string(Path.str());
+ if (Component == "builtins") {
+ SmallString<128> Path(getDriver().SysRoot);
+ llvm::sys::path::append(Path, "/usr/lib/libcompiler_rt.a");
+ return std::string(Path);
+ }
+ SmallString<128> P(getDriver().ResourceDir);
+ std::string CRTBasename =
+ buildCompilerRTBasename(Args, Component, Type, /*AddArch=*/false);
+ llvm::sys::path::append(P, "lib", CRTBasename);
+ // Checks if this is the base system case which uses a different location.
+ if (getVFS().exists(P))
+ return std::string(P);
+ return ToolChain::getCompilerRT(Args, Component, Type);
}
Tool *OpenBSD::buildAssembler() const {
@@ -321,3 +390,13 @@ Tool *OpenBSD::buildAssembler() const {
Tool *OpenBSD::buildLinker() const { return new tools::openbsd::Linker(*this); }
bool OpenBSD::HasNativeLLVMSupport() const { return true; }
+
+ToolChain::UnwindTableLevel
+OpenBSD::getDefaultUnwindTableLevel(const ArgList &Args) const {
+ switch (getArch()) {
+ case llvm::Triple::arm:
+ return UnwindTableLevel::None;
+ default:
+ return UnwindTableLevel::Asynchronous;
+ }
+}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/OpenBSD.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/OpenBSD.h
index 4932ed5c609c..b4350e72d5d2 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/OpenBSD.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/OpenBSD.h
@@ -18,9 +18,9 @@ namespace clang {
namespace driver {
namespace tools {
-/// openbsd -- Directly call GNU Binutils assembler and linker
+/// Directly call GNU Binutils assembler and linker
namespace openbsd {
-class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
+class LLVM_LIBRARY_VISIBILITY Assembler final : public Tool {
public:
Assembler(const ToolChain &TC)
: Tool("openbsd::Assembler", "assembler", TC) {}
@@ -33,7 +33,7 @@ public:
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
public:
Linker(const ToolChain &TC) : Tool("openbsd::Linker", "linker", TC) {}
@@ -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;
@@ -80,6 +82,9 @@ public:
std::string getCompilerRT(const llvm::opt::ArgList &Args, StringRef Component,
FileType Type = ToolChain::FT_Static) const override;
+ UnwindTableLevel
+ getDefaultUnwindTableLevel(const llvm::opt::ArgList &Args) const override;
+
LangOptions::StackProtectorMode
GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
return LangOptions::SSPStrong;
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/PPCFreeBSD.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/PPCFreeBSD.cpp
new file mode 100644
index 000000000000..8d381c4f1437
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/PPCFreeBSD.cpp
@@ -0,0 +1,28 @@
+//===-- PPCFreeBSD.cpp - PowerPC ToolChain Implementations ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "PPCFreeBSD.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/Options.h"
+#include "llvm/Support/Path.h"
+
+using namespace clang::driver::toolchains;
+using namespace llvm::opt;
+
+void PPCFreeBSDToolChain::AddClangSystemIncludeArgs(
+ const ArgList &DriverArgs, ArgStringList &CC1Args) const {
+ if (!DriverArgs.hasArg(clang::driver::options::OPT_nostdinc) &&
+ !DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+ const Driver &D = getDriver();
+ SmallString<128> P(D.ResourceDir);
+ llvm::sys::path::append(P, "include", "ppc_wrappers");
+ addSystemInclude(DriverArgs, CC1Args, P);
+ }
+
+ FreeBSD::AddClangSystemIncludeArgs(DriverArgs, CC1Args);
+}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/PPCFreeBSD.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/PPCFreeBSD.h
new file mode 100644
index 000000000000..d5d9cf4e83a0
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/PPCFreeBSD.h
@@ -0,0 +1,33 @@
+//===--- PPCFreeBSD.h - PowerPC ToolChain Implementations -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_PPC_FREEBSD_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_PPC_FREEBSD_H
+
+#include "FreeBSD.h"
+
+namespace clang {
+namespace driver {
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY PPCFreeBSDToolChain : public FreeBSD {
+public:
+ PPCFreeBSDToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args)
+ : FreeBSD(D, Triple, Args) {}
+
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+};
+
+} // end namespace toolchains
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_PPC_FREEBSD_H
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/PPCLinux.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/PPCLinux.cpp
index af2e3a21a0af..0ed0f91ad166 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/PPCLinux.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/PPCLinux.cpp
@@ -8,11 +8,54 @@
#include "PPCLinux.h"
#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
+using namespace clang::driver;
using namespace clang::driver::toolchains;
using namespace llvm::opt;
+using namespace llvm::sys;
+
+// Glibc older than 2.32 doesn't fully support IEEE float128. Here we check
+// glibc version by looking at dynamic linker name.
+static bool GlibcSupportsFloat128(const std::string &Linker) {
+ llvm::SmallVector<char, 16> Path;
+
+ // Resolve potential symlinks to linker.
+ if (fs::real_path(Linker, Path))
+ return false;
+ llvm::StringRef LinkerName =
+ path::filename(llvm::StringRef(Path.data(), Path.size()));
+
+ // Since glibc 2.34, the installed .so file is not symlink anymore. But we can
+ // still safely assume it's newer than 2.32.
+ if (LinkerName.starts_with("ld64.so"))
+ return true;
+
+ if (!LinkerName.starts_with("ld-2."))
+ return false;
+ unsigned Minor = (LinkerName[5] - '0') * 10 + (LinkerName[6] - '0');
+ if (Minor < 32)
+ return false;
+
+ return true;
+}
+
+PPCLinuxToolChain::PPCLinuxToolChain(const Driver &D,
+ const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args)
+ : Linux(D, Triple, Args) {
+ if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
+ StringRef ABIName = A->getValue();
+
+ if ((ABIName == "ieeelongdouble" &&
+ !SupportIEEEFloat128(D, Triple, Args)) ||
+ (ABIName == "ibmlongdouble" && !supportIBMLongDouble(D, Args)))
+ D.Diag(diag::warn_drv_unsupported_float_abi_by_lib) << ABIName;
+ }
+}
void PPCLinuxToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
@@ -26,3 +69,35 @@ void PPCLinuxToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
Linux::AddClangSystemIncludeArgs(DriverArgs, CC1Args);
}
+
+bool PPCLinuxToolChain::supportIBMLongDouble(
+ const Driver &D, const llvm::opt::ArgList &Args) const {
+ if (Args.hasArg(options::OPT_nostdlib, options::OPT_nostdlibxx))
+ return true;
+
+ CXXStdlibType StdLib = ToolChain::GetCXXStdlibType(Args);
+ if (StdLib == CST_Libstdcxx)
+ return true;
+
+ return StdLib == CST_Libcxx && !defaultToIEEELongDouble();
+}
+
+bool PPCLinuxToolChain::SupportIEEEFloat128(
+ const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args) const {
+ if (!Triple.isLittleEndian() || !Triple.isPPC64())
+ return false;
+
+ if (Args.hasArg(options::OPT_nostdlib, options::OPT_nostdlibxx))
+ return true;
+
+ CXXStdlibType StdLib = ToolChain::GetCXXStdlibType(Args);
+ bool HasUnsupportedCXXLib =
+ (StdLib == CST_Libcxx && !defaultToIEEELongDouble()) ||
+ (StdLib == CST_Libstdcxx &&
+ GCCInstallation.getVersion().isOlderThan(12, 1, 0));
+
+ std::string Linker = Linux::getDynamicLinker(Args);
+ return GlibcSupportsFloat128((Twine(D.DyldPrefix) + Linker).str()) &&
+ !(D.CCCIsCXX() && HasUnsupportedCXXLib);
+}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/PPCLinux.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/PPCLinux.h
index b3ef7b61dc3a..63adaff6be9c 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/PPCLinux.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/PPCLinux.h
@@ -18,12 +18,17 @@ namespace toolchains {
class LLVM_LIBRARY_VISIBILITY PPCLinuxToolChain : public Linux {
public:
PPCLinuxToolChain(const Driver &D, const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args)
- : Linux(D, Triple, Args) {}
+ const llvm::opt::ArgList &Args);
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+
+private:
+ bool SupportIEEEFloat128(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args) const;
+ bool supportIBMLongDouble(const Driver &D,
+ const llvm::opt::ArgList &Args) const;
};
} // end namespace toolchains
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/PS4CPU.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/PS4CPU.cpp
index 383b0c50d410..8ba8b80cfec7 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/PS4CPU.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/PS4CPU.cpp
@@ -7,8 +7,8 @@
//===----------------------------------------------------------------------===//
#include "PS4CPU.h"
-#include "FreeBSD.h"
#include "CommonArgs.h"
+#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
@@ -23,10 +23,18 @@ using namespace clang::driver;
using namespace clang;
using namespace llvm::opt;
-using clang::driver::tools::AddLinkerInputs;
+// Helper to paste bits of an option together and return a saved string.
+static const char *makeArgString(const ArgList &Args, const char *Prefix,
+ const char *Base, const char *Suffix) {
+ // Basically "Prefix + Base + Suffix" all converted to Twine then saved.
+ return Args.MakeArgString(Twine(StringRef(Prefix), Base) + Suffix);
+}
+
+void tools::PScpu::addProfileRTArgs(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ assert(TC.getTriple().isPS());
+ auto &PSTC = static_cast<const toolchains::PS4PS5Base &>(TC);
-void tools::PS4cpu::addProfileRTArgs(const ToolChain &TC, const ArgList &Args,
- ArgStringList &CmdArgs) {
if ((Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
false) ||
Args.hasFlag(options::OPT_fprofile_generate,
@@ -43,14 +51,16 @@ void tools::PS4cpu::addProfileRTArgs(const ToolChain &TC, const ArgList &Args,
options::OPT_fno_profile_generate, false) ||
Args.hasArg(options::OPT_fcreate_profile) ||
Args.hasArg(options::OPT_coverage)))
- CmdArgs.push_back("--dependent-lib=libclang_rt.profile-x86_64.a");
+ CmdArgs.push_back(makeArgString(
+ Args, "--dependent-lib=", PSTC.getProfileRTLibName(), ""));
}
-void tools::PS4cpu::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+void tools::PScpu::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
+ auto &TC = static_cast<const toolchains::PS4PS5Base &>(getToolChain());
claimNoWarnArgs(Args);
ArgStringList CmdArgs;
@@ -64,40 +74,57 @@ void tools::PS4cpu::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
assert(Input.isFilename() && "Invalid input.");
CmdArgs.push_back(Input.getFilename());
- const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("orbis-as"));
+ std::string AsName = TC.qualifyPSCmdName("as");
+ const char *Exec = Args.MakeArgString(TC.GetProgramPath(AsName.c_str()));
C.addCommand(std::make_unique<Command>(JA, *this,
ResponseFileSupport::AtFileUTF8(),
Exec, CmdArgs, Inputs, Output));
}
-static void AddPS4SanitizerArgs(const ToolChain &TC, ArgStringList &CmdArgs) {
- const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
- if (SanArgs.needsUbsanRt()) {
- CmdArgs.push_back("-lSceDbgUBSanitizer_stub_weak");
- }
- if (SanArgs.needsAsanRt()) {
- CmdArgs.push_back("-lSceDbgAddressSanitizer_stub_weak");
- }
+void tools::PScpu::addSanitizerArgs(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ assert(TC.getTriple().isPS());
+ auto &PSTC = static_cast<const toolchains::PS4PS5Base &>(TC);
+ PSTC.addSanitizerArgs(Args, CmdArgs, "--dependent-lib=lib", ".a");
}
-void tools::PS4cpu::addSanitizerArgs(const ToolChain &TC,
- ArgStringList &CmdArgs) {
- const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
+void toolchains::PS4CPU::addSanitizerArgs(const ArgList &Args,
+ ArgStringList &CmdArgs,
+ const char *Prefix,
+ const char *Suffix) const {
+ auto arg = [&](const char *Name) -> const char * {
+ return makeArgString(Args, Prefix, Name, Suffix);
+ };
+ const SanitizerArgs &SanArgs = getSanitizerArgs(Args);
if (SanArgs.needsUbsanRt())
- CmdArgs.push_back("--dependent-lib=libSceDbgUBSanitizer_stub_weak.a");
+ CmdArgs.push_back(arg("SceDbgUBSanitizer_stub_weak"));
if (SanArgs.needsAsanRt())
- CmdArgs.push_back("--dependent-lib=libSceDbgAddressSanitizer_stub_weak.a");
+ CmdArgs.push_back(arg("SceDbgAddressSanitizer_stub_weak"));
}
-void tools::PS4cpu::Link::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
- const toolchains::FreeBSD &ToolChain =
- static_cast<const toolchains::FreeBSD &>(getToolChain());
- const Driver &D = ToolChain.getDriver();
+void toolchains::PS5CPU::addSanitizerArgs(const ArgList &Args,
+ ArgStringList &CmdArgs,
+ const char *Prefix,
+ const char *Suffix) const {
+ auto arg = [&](const char *Name) -> const char * {
+ return makeArgString(Args, Prefix, Name, Suffix);
+ };
+ const SanitizerArgs &SanArgs = getSanitizerArgs(Args);
+ if (SanArgs.needsUbsanRt())
+ CmdArgs.push_back(arg("SceUBSanitizer_nosubmission_stub_weak"));
+ if (SanArgs.needsAsanRt())
+ CmdArgs.push_back(arg("SceAddressSanitizer_nosubmission_stub_weak"));
+ if (SanArgs.needsTsanRt())
+ CmdArgs.push_back(arg("SceThreadSanitizer_nosubmission_stub_weak"));
+}
+
+void tools::PScpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ auto &TC = static_cast<const toolchains::PS4PS5Base &>(getToolChain());
+ const Driver &D = TC.getDriver();
ArgStringList CmdArgs;
// Silence warning for "clang -g foo.o -o foo"
@@ -117,119 +144,195 @@ void tools::PS4cpu::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_rdynamic))
CmdArgs.push_back("-export-dynamic");
if (Args.hasArg(options::OPT_shared))
- CmdArgs.push_back("--oformat=so");
+ CmdArgs.push_back("--shared");
+ assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- } else {
- assert(Output.isNothing() && "Invalid output.");
}
- if(!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
- AddPS4SanitizerArgs(ToolChain, CmdArgs);
+ const bool UseLTO = D.isUsingLTO();
+ const bool UseJMC =
+ Args.hasFlag(options::OPT_fjmc, options::OPT_fno_jmc, false);
+ const bool IsPS4 = TC.getTriple().isPS4();
- Args.AddAllArgs(CmdArgs, options::OPT_L);
- Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
- Args.AddAllArgs(CmdArgs, options::OPT_e);
- Args.AddAllArgs(CmdArgs, options::OPT_s);
- Args.AddAllArgs(CmdArgs, options::OPT_t);
- Args.AddAllArgs(CmdArgs, options::OPT_r);
+ const char *PS4LTOArgs = "";
+ auto AddCodeGenFlag = [&](Twine Flag) {
+ if (IsPS4)
+ PS4LTOArgs = Args.MakeArgString(Twine(PS4LTOArgs) + " " + Flag);
+ else
+ CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=") + Flag));
+ };
+
+ if (UseLTO) {
+ // We default to creating the arange section, but LTO does not. Enable it
+ // here.
+ AddCodeGenFlag("-generate-arange-section");
+
+ // This tells LTO to perform JustMyCode instrumentation.
+ if (UseJMC)
+ AddCodeGenFlag("-enable-jmc-instrument");
+
+ if (Arg *A = Args.getLastArg(options::OPT_fcrash_diagnostics_dir))
+ AddCodeGenFlag(Twine("-crash-diagnostics-dir=") + A->getValue());
+
+ StringRef Parallelism = getLTOParallelism(Args, D);
+ if (!Parallelism.empty()) {
+ if (IsPS4)
+ AddCodeGenFlag(Twine("-threads=") + Parallelism);
+ else
+ CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=jobs=") + Parallelism));
+ }
+
+ if (IsPS4) {
+ const char *Prefix = nullptr;
+ if (D.getLTOMode() == LTOK_Thin)
+ Prefix = "-lto-thin-debug-options=";
+ else if (D.getLTOMode() == LTOK_Full)
+ Prefix = "-lto-debug-options=";
+ else
+ llvm_unreachable("new LTO mode?");
+
+ CmdArgs.push_back(Args.MakeArgString(Twine(Prefix) + PS4LTOArgs));
+ }
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
+ TC.addSanitizerArgs(Args, CmdArgs, "-l", "");
+
+ if (D.isUsingLTO() && Args.hasArg(options::OPT_funified_lto)) {
+ if (D.getLTOMode() == LTOK_Thin)
+ CmdArgs.push_back("--lto=thin");
+ else if (D.getLTOMode() == LTOK_Full)
+ CmdArgs.push_back("--lto=full");
+ }
+
+ Args.addAllArgs(CmdArgs,
+ {options::OPT_L, options::OPT_T_Group, options::OPT_s,
+ options::OPT_t, options::OPT_r});
if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
CmdArgs.push_back("--no-demangle");
- AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
+ AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
if (Args.hasArg(options::OPT_pthread)) {
CmdArgs.push_back("-lpthread");
}
+ if (UseJMC) {
+ CmdArgs.push_back("--whole-archive");
+ if (IsPS4)
+ CmdArgs.push_back("-lSceDbgJmc");
+ else
+ CmdArgs.push_back("-lSceJmc_nosubmission");
+ CmdArgs.push_back("--no-whole-archive");
+ }
+
if (Args.hasArg(options::OPT_fuse_ld_EQ)) {
D.Diag(diag::err_drv_unsupported_opt_for_target)
- << "-fuse-ld" << getToolChain().getTriple().str();
+ << "-fuse-ld" << TC.getTriple().str();
}
- const char *Exec =
- Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld"));
+ std::string LdName = TC.qualifyPSCmdName(TC.getLinkerBaseName());
+ const char *Exec = Args.MakeArgString(TC.GetProgramPath(LdName.c_str()));
C.addCommand(std::make_unique<Command>(JA, *this,
ResponseFileSupport::AtFileUTF8(),
Exec, CmdArgs, Inputs, Output));
}
-toolchains::PS4CPU::PS4CPU(const Driver &D, const llvm::Triple &Triple,
- const ArgList &Args)
+toolchains::PS4PS5Base::PS4PS5Base(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args, StringRef Platform,
+ const char *EnvVar)
: Generic_ELF(D, Triple, Args) {
if (Args.hasArg(clang::driver::options::OPT_static))
- D.Diag(clang::diag::err_drv_unsupported_opt_for_target) << "-static"
- << "PS4";
-
- // Determine where to find the PS4 libraries. We use SCE_ORBIS_SDK_DIR
- // if it exists; otherwise use the driver's installation path, which
- // should be <SDK_DIR>/host_tools/bin.
-
- SmallString<512> PS4SDKDir;
- if (const char *EnvValue = getenv("SCE_ORBIS_SDK_DIR")) {
- if (!llvm::sys::fs::exists(EnvValue))
- getDriver().Diag(clang::diag::warn_drv_ps4_sdk_dir) << EnvValue;
- PS4SDKDir = EnvValue;
- } else {
- PS4SDKDir = getDriver().Dir;
- llvm::sys::path::append(PS4SDKDir, "/../../");
- }
+ D.Diag(clang::diag::err_drv_unsupported_opt_for_target)
+ << "-static" << Platform;
- // By default, the driver won't report a warning if it can't find
- // PS4's include or lib directories. This behavior could be changed if
- // -Weverything or -Winvalid-or-nonexistent-directory options are passed.
+ // Determine where to find the PS4/PS5 libraries.
// If -isysroot was passed, use that as the SDK base path.
- std::string PrefixDir;
+ // If not, we use the EnvVar if it exists; otherwise use the driver's
+ // installation path, which should be <SDK_DIR>/host_tools/bin.
+ SmallString<80> Whence;
if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
- PrefixDir = A->getValue();
- if (!llvm::sys::fs::exists(PrefixDir))
- getDriver().Diag(clang::diag::warn_missing_sysroot) << PrefixDir;
- } else
- PrefixDir = std::string(PS4SDKDir.str());
-
- SmallString<512> PS4SDKIncludeDir(PrefixDir);
- llvm::sys::path::append(PS4SDKIncludeDir, "target/include");
+ SDKRootDir = A->getValue();
+ if (!llvm::sys::fs::exists(SDKRootDir))
+ D.Diag(clang::diag::warn_missing_sysroot) << SDKRootDir;
+ Whence = A->getSpelling();
+ } else if (const char *EnvValue = getenv(EnvVar)) {
+ SDKRootDir = EnvValue;
+ Whence = { "environment variable '", EnvVar, "'" };
+ } else {
+ SDKRootDir = D.Dir + "/../../";
+ Whence = "compiler's location";
+ }
+
+ SmallString<512> SDKIncludeDir(SDKRootDir);
+ llvm::sys::path::append(SDKIncludeDir, "target/include");
if (!Args.hasArg(options::OPT_nostdinc) &&
!Args.hasArg(options::OPT_nostdlibinc) &&
!Args.hasArg(options::OPT_isysroot) &&
!Args.hasArg(options::OPT__sysroot_EQ) &&
- !llvm::sys::fs::exists(PS4SDKIncludeDir)) {
- getDriver().Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
- << "PS4 system headers" << PS4SDKIncludeDir;
+ !llvm::sys::fs::exists(SDKIncludeDir)) {
+ D.Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
+ << Twine(Platform, " system headers").str() << SDKIncludeDir << Whence;
}
- SmallString<512> PS4SDKLibDir(PS4SDKDir);
- llvm::sys::path::append(PS4SDKLibDir, "target/lib");
+ SmallString<512> SDKLibDir(SDKRootDir);
+ llvm::sys::path::append(SDKLibDir, "target/lib");
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs) &&
!Args.hasArg(options::OPT__sysroot_EQ) && !Args.hasArg(options::OPT_E) &&
!Args.hasArg(options::OPT_c) && !Args.hasArg(options::OPT_S) &&
!Args.hasArg(options::OPT_emit_ast) &&
- !llvm::sys::fs::exists(PS4SDKLibDir)) {
- getDriver().Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
- << "PS4 system libraries" << PS4SDKLibDir;
+ !llvm::sys::fs::exists(SDKLibDir)) {
+ D.Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
+ << Twine(Platform, " system libraries").str() << SDKLibDir << Whence;
return;
}
- getFilePaths().push_back(std::string(PS4SDKLibDir.str()));
+ getFilePaths().push_back(std::string(SDKLibDir));
}
-Tool *toolchains::PS4CPU::buildAssembler() const {
- return new tools::PS4cpu::Assemble(*this);
+void toolchains::PS4PS5Base::AddClangSystemIncludeArgs(
+ const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ const Driver &D = getDriver();
+
+ if (DriverArgs.hasArg(options::OPT_nostdinc))
+ return;
+
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+ SmallString<128> Dir(D.ResourceDir);
+ llvm::sys::path::append(Dir, "include");
+ addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ }
+
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+
+ addExternCSystemInclude(DriverArgs, CC1Args,
+ SDKRootDir + "/target/include");
+ addExternCSystemInclude(DriverArgs, CC1Args,
+ SDKRootDir + "/target/include_common");
}
-Tool *toolchains::PS4CPU::buildLinker() const {
- return new tools::PS4cpu::Link(*this);
+Tool *toolchains::PS4CPU::buildAssembler() const {
+ return new tools::PScpu::Assembler(*this);
}
-bool toolchains::PS4CPU::isPICDefault() const { return true; }
+Tool *toolchains::PS5CPU::buildAssembler() const {
+ // PS5 does not support an external assembler.
+ getDriver().Diag(clang::diag::err_no_external_assembler);
+ return nullptr;
+}
-bool toolchains::PS4CPU::HasNativeLLVMSupport() const { return true; }
+Tool *toolchains::PS4PS5Base::buildLinker() const {
+ return new tools::PScpu::Linker(*this);
+}
-SanitizerMask toolchains::PS4CPU::getSupportedSanitizers() const {
+SanitizerMask toolchains::PS4PS5Base::getSupportedSanitizers() const {
SanitizerMask Res = ToolChain::getSupportedSanitizers();
Res |= SanitizerKind::Address;
Res |= SanitizerKind::PointerCompare;
@@ -238,10 +341,16 @@ SanitizerMask toolchains::PS4CPU::getSupportedSanitizers() const {
return Res;
}
-void toolchains::PS4CPU::addClangTargetOptions(
+SanitizerMask toolchains::PS5CPU::getSupportedSanitizers() const {
+ SanitizerMask Res = PS4PS5Base::getSupportedSanitizers();
+ Res |= SanitizerKind::Thread;
+ return Res;
+}
+
+void toolchains::PS4PS5Base::addClangTargetOptions(
const ArgList &DriverArgs, ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadingKind) const {
- // PS4 does not use init arrays.
+ // PS4/PS5 do not use init arrays.
if (DriverArgs.hasArg(options::OPT_fuse_init_array)) {
Arg *A = DriverArgs.getLastArg(options::OPT_fuse_init_array);
getDriver().Diag(clang::diag::err_drv_unsupported_opt_for_target)
@@ -250,6 +359,12 @@ void toolchains::PS4CPU::addClangTargetOptions(
CC1Args.push_back("-fno-use-init-array");
+ // Default to -fvisibility-global-new-delete=source for PS5.
+ if (getTriple().isPS5() &&
+ !DriverArgs.hasArg(options::OPT_fvisibility_global_new_delete_EQ,
+ options::OPT_fvisibility_global_new_delete_hidden))
+ CC1Args.push_back("-fvisibility-global-new-delete=source");
+
const Arg *A =
DriverArgs.getLastArg(options::OPT_fvisibility_from_dllstorageclass,
options::OPT_fno_visibility_from_dllstorageclass);
@@ -282,3 +397,13 @@ void toolchains::PS4CPU::addClangTargetOptions(
CC1Args.push_back("-fvisibility-externs-nodllstorageclass=default");
}
}
+
+// PS4 toolchain.
+toolchains::PS4CPU::PS4CPU(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args)
+ : PS4PS5Base(D, Triple, Args, "PS4", "SCE_ORBIS_SDK_DIR") {}
+
+// PS5 toolchain.
+toolchains::PS5CPU::PS5CPU(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args)
+ : PS4PS5Base(D, Triple, Args, "PS5", "SCE_PROSPERO_SDK_DIR") {}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/PS4CPU.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/PS4CPU.h
index 5f5d0e57d4ea..fee80e77462f 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/PS4CPU.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/PS4CPU.h
@@ -18,61 +18,66 @@ namespace clang {
namespace driver {
namespace tools {
-namespace PS4cpu {
+namespace PScpu {
+// Functions/classes in this namespace support both PS4 and PS5.
void addProfileRTArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);
-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 {
+class LLVM_LIBRARY_VISIBILITY Assembler final : public Tool {
public:
- Assemble(const ToolChain &TC) : Tool("PS4cpu::Assemble", "assembler", TC) {}
+ Assembler(const ToolChain &TC) : Tool("PScpu::Assembler", "assembler", TC) {}
bool hasIntegratedCPP() const override { return false; }
void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
+ const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
public:
- Link(const ToolChain &TC) : Tool("PS4cpu::Link", "linker", TC) {}
+ Linker(const ToolChain &TC) : Tool("PScpu::Linker", "linker", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
+ const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
-} // end namespace PS4cpu
+} // namespace PScpu
} // namespace tools
namespace toolchains {
-class LLVM_LIBRARY_VISIBILITY PS4CPU : public Generic_ELF {
+// Common Toolchain base class for PS4 and PS5.
+class LLVM_LIBRARY_VISIBILITY PS4PS5Base : public Generic_ELF {
public:
- PS4CPU(const Driver &D, const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args);
+ PS4PS5Base(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args, StringRef Platform,
+ const char *EnvVar);
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
// No support for finding a C++ standard library yet.
- void addLibCxxIncludePaths(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override {}
- void addLibStdCxxIncludePaths(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override {}
+ void addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override {
+ }
+ void
+ addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override {}
bool IsMathErrnoDefault() const override { return false; }
bool IsObjCNonFragileABIDefault() const override { return true; }
- bool HasNativeLLVMSupport() const override;
- bool isPICDefault() const override;
+ bool HasNativeLLVMSupport() const override { return true; }
+ bool isPICDefault() const override { return true; }
LangOptions::StackProtectorMode
GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
@@ -85,14 +90,9 @@ public:
SanitizerMask getSupportedSanitizers() const override;
- // PS4 toolchain uses legacy thin LTO API, which is not
- // capable of unit splitting.
- bool canSplitThinLTOUnit() const override { return false; }
-
void addClangTargetOptions(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args,
- Action::OffloadKind DeviceOffloadingKind) const override;
+ const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadingKind) const override;
llvm::DenormalMode getDefaultDenormalModeForType(
const llvm::opt::ArgList &DriverArgs, const JobAction &JA,
@@ -101,11 +101,73 @@ public:
return llvm::DenormalMode::getPreserveSign();
}
- bool useRelaxRelocations() const override { return true; }
+ // Helper methods for PS4/PS5.
+ virtual const char *getLinkerBaseName() const = 0;
+ virtual std::string qualifyPSCmdName(StringRef CmdName) const = 0;
+ virtual void addSanitizerArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs,
+ const char *Prefix,
+ const char *Suffix) const = 0;
+ virtual const char *getProfileRTLibName() const = 0;
protected:
- Tool *buildAssembler() const override;
Tool *buildLinker() const override;
+
+private:
+ // We compute the SDK root dir in the ctor, and use it later.
+ std::string SDKRootDir;
+};
+
+// PS4-specific Toolchain class.
+class LLVM_LIBRARY_VISIBILITY PS4CPU : public PS4PS5Base {
+public:
+ PS4CPU(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ unsigned GetDefaultDwarfVersion() const override { return 4; }
+
+ // PS4 toolchain uses legacy thin LTO API, which is not
+ // capable of unit splitting.
+ bool canSplitThinLTOUnit() const override { return false; }
+
+ const char *getLinkerBaseName() const override { return "ld"; }
+ std::string qualifyPSCmdName(StringRef CmdName) const override {
+ return Twine("orbis-", CmdName).str();
+ }
+ void addSanitizerArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs, const char *Prefix,
+ const char *Suffix) const override;
+ const char *getProfileRTLibName() const override {
+ return "libclang_rt.profile-x86_64.a";
+ }
+
+protected:
+ Tool *buildAssembler() const override;
+};
+
+// PS5-specific Toolchain class.
+class LLVM_LIBRARY_VISIBILITY PS5CPU : public PS4PS5Base {
+public:
+ PS5CPU(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ unsigned GetDefaultDwarfVersion() const override { return 5; }
+
+ SanitizerMask getSupportedSanitizers() const override;
+
+ const char *getLinkerBaseName() const override { return "lld"; }
+ std::string qualifyPSCmdName(StringRef CmdName) const override {
+ return Twine("prospero-", CmdName).str();
+ }
+ void addSanitizerArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs, const char *Prefix,
+ const char *Suffix) const override;
+ const char *getProfileRTLibName() const override {
+ return "libclang_rt.profile-x86_64_nosubmission.a";
+ }
+
+protected:
+ Tool *buildAssembler() const override;
};
} // end namespace toolchains
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/RISCVToolchain.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
index 714325a2db39..5e4fa4d5331f 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
@@ -1,4 +1,4 @@
-//===--- RISCVToolchain.cpp - RISCV ToolChain Implementations ---*- C++ -*-===//
+//===--- RISCVToolchain.cpp - RISC-V ToolChain Implementations --*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -46,17 +46,17 @@ bool RISCVToolChain::hasGCCToolchain(const Driver &D,
return llvm::sys::fs::exists(GCCDir);
}
-/// RISCV Toolchain
+/// RISC-V Toolchain
RISCVToolChain::RISCVToolChain(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
GCCInstallation.init(Triple, Args);
if (GCCInstallation.isValid()) {
Multilibs = GCCInstallation.getMultilibs();
- SelectedMultilib = GCCInstallation.getMultilib();
+ SelectedMultilibs.assign({GCCInstallation.getMultilib()});
path_list &Paths = getFilePaths();
// Add toolchain/multilib specific file paths.
- addMultilibsFilePaths(D, Multilibs, SelectedMultilib,
+ addMultilibsFilePaths(D, Multilibs, SelectedMultilibs.back(),
GCCInstallation.getInstallPath(), Paths);
getFilePaths().push_back(GCCInstallation.getInstallPath().str());
ToolChain::path_list &PPaths = getProgramPaths();
@@ -98,6 +98,12 @@ void RISCVToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
if (DriverArgs.hasArg(options::OPT_nostdinc))
return;
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+ SmallString<128> Dir(getDriver().ResourceDir);
+ llvm::sys::path::append(Dir, "include");
+ addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ }
+
if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
SmallString<128> Dir(computeSysRoot());
llvm::sys::path::append(Dir, "include");
@@ -135,7 +141,7 @@ std::string RISCVToolChain::computeSysRoot() const {
if (!llvm::sys::fs::exists(SysRootDir))
return std::string();
- return std::string(SysRootDir.str());
+ return std::string(SysRootDir);
}
void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -157,6 +163,7 @@ void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
} else {
CmdArgs.push_back("elf32lriscv");
}
+ CmdArgs.push_back("-X");
std::string Linker = getToolChain().GetLinkerPath();
@@ -183,19 +190,21 @@ void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
- Args.AddAllArgs(CmdArgs, options::OPT_L);
- Args.AddAllArgs(CmdArgs, options::OPT_u);
+ Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u});
+
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
- Args.AddAllArgs(CmdArgs,
- {options::OPT_T_Group, options::OPT_e, options::OPT_s,
- options::OPT_t, options::OPT_Z_Flag, options::OPT_r});
+ Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s,
+ options::OPT_t, options::OPT_r});
// TODO: add C++ includes and libs if compiling C++.
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
- if (ToolChain.ShouldLinkCXXStdlib(Args))
- ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (D.CCCIsCXX()) {
+ if (ToolChain.ShouldLinkCXXStdlib(Args))
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ CmdArgs.push_back("-lm");
+ }
CmdArgs.push_back("--start-group");
CmdArgs.push_back("-lc");
CmdArgs.push_back("-lgloss");
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/RISCVToolchain.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/RISCVToolchain.h
index 62099bee0404..cec817ef7190 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/RISCVToolchain.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/RISCVToolchain.h
@@ -1,4 +1,4 @@
-//===--- RISCVToolchain.h - RISCV ToolChain Implementations -----*- C++ -*-===//
+//===--- RISCVToolchain.h - RISC-V ToolChain Implementations ----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -22,7 +22,6 @@ public:
const llvm::opt::ArgList &Args);
static bool hasGCCToolchain(const Driver &D, const llvm::opt::ArgList &Args);
- bool IsIntegratedAssemblerDefault() const override { return true; }
void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind) const override;
@@ -47,7 +46,7 @@ private:
namespace tools {
namespace RISCV {
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
public:
Linker(const ToolChain &TC) : Tool("RISCV::Linker", "ld", TC) {}
bool hasIntegratedCPP() const override { return false; }
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/ROCm.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/ROCm.h
index bb482be68260..dceb0ab03669 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/ROCm.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/ROCm.h
@@ -15,13 +15,33 @@
#include "clang/Driver/Options.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/VersionTuple.h"
+#include "llvm/TargetParser/Triple.h"
namespace clang {
namespace driver {
+/// ABI version of device library.
+struct DeviceLibABIVersion {
+ unsigned ABIVersion = 0;
+ DeviceLibABIVersion(unsigned V) : ABIVersion(V) {}
+ static DeviceLibABIVersion fromCodeObjectVersion(unsigned CodeObjectVersion) {
+ if (CodeObjectVersion < 4)
+ CodeObjectVersion = 4;
+ return DeviceLibABIVersion(CodeObjectVersion * 100);
+ }
+ /// Whether ABI version bc file is requested.
+ /// ABIVersion is code object version multiplied by 100. Code object v4
+ /// and below works with ROCm 5.0 and below which does not have
+ /// abi_version_*.bc. Code object v5 requires abi_version_500.bc.
+ bool requiresLibrary() { return ABIVersion >= 500; }
+ std::string toString() {
+ assert(ABIVersion % 100 == 0 && "Not supported");
+ return Twine(ABIVersion / 100).str();
+ }
+};
+
/// A class to find a viable ROCM installation
/// TODO: Generalize to handle libclc.
class RocmInstallationDetector {
@@ -57,6 +77,9 @@ private:
const Driver &D;
bool HasHIPRuntime = false;
bool HasDeviceLibrary = false;
+ bool HasHIPStdParLibrary = false;
+ bool HasRocThrustLibrary = false;
+ bool HasRocPrimLibrary = false;
// Default version if not detected or specified.
const unsigned DefaultVersionMajor = 3;
@@ -76,6 +99,13 @@ private:
std::vector<std::string> RocmDeviceLibPathArg;
// HIP runtime path specified by --hip-path.
StringRef HIPPathArg;
+ // HIP Standard Parallel Algorithm acceleration library specified by
+ // --hipstdpar-path
+ StringRef HIPStdParPathArg;
+ // rocThrust algorithm library specified by --hipstdpar-thrust-path
+ StringRef HIPRocThrustPathArg;
+ // rocPrim algorithm library specified by --hipstdpar-prim-path
+ StringRef HIPRocPrimPathArg;
// HIP version specified by --hip-version.
StringRef HIPVersionArg;
// Wheter -nogpulib is specified.
@@ -87,6 +117,7 @@ private:
SmallString<0> LibPath;
SmallString<0> LibDevicePath;
SmallString<0> IncludePath;
+ SmallString<0> SharePath;
llvm::StringMap<std::string> LibDeviceMap;
// Libraries that are always linked.
@@ -107,6 +138,10 @@ private:
ConditionalLibrary DenormalsAreZero;
ConditionalLibrary CorrectlyRoundedSqrt;
+ // Maps ABI version to library path. The version number is in the format of
+ // three digits as used in the ABI version library name.
+ std::map<unsigned, std::string> ABIVersionMap;
+
// Cache ROCm installation search paths.
SmallVector<Candidate, 4> ROCmSearchDirs;
bool PrintROCmSearchDirs;
@@ -142,7 +177,12 @@ public:
getCommonBitcodeLibs(const llvm::opt::ArgList &DriverArgs,
StringRef LibDeviceFile, bool Wave64, bool DAZ,
bool FiniteOnly, bool UnsafeMathOpt,
- bool FastRelaxedMath, bool CorrectSqrt) const;
+ bool FastRelaxedMath, bool CorrectSqrt,
+ DeviceLibABIVersion ABIVer, bool isOpenMP) const;
+ /// Check file paths of default bitcode libraries common to AMDGPU based
+ /// toolchains. \returns false if there are invalid or missing files.
+ bool checkCommonBitcodeLibs(StringRef GPUArch, StringRef LibDeviceFile,
+ DeviceLibABIVersion ABIVer) const;
/// Check whether we detected a valid HIP runtime.
bool hasHIPRuntime() const { return HasHIPRuntime; }
@@ -150,6 +190,9 @@ public:
/// Check whether we detected a valid ROCm device library.
bool hasDeviceLibrary() const { return HasDeviceLibrary; }
+ /// Check whether we detected a valid HIP STDPAR Acceleration library.
+ bool hasHIPStdParLibrary() const { return HasHIPStdParLibrary; }
+
/// Print information about the detected ROCm installation.
void print(raw_ostream &OS) const;
@@ -214,9 +257,19 @@ public:
return CorrectlyRoundedSqrt.get(Enabled);
}
+ StringRef getABIVersionPath(DeviceLibABIVersion ABIVer) const {
+ auto Loc = ABIVersionMap.find(ABIVer.ABIVersion);
+ if (Loc == ABIVersionMap.end())
+ return StringRef();
+ return Loc->second;
+ }
+
/// Get libdevice file for given architecture
- std::string getLibDeviceFile(StringRef Gpu) const {
- return LibDeviceMap.lookup(Gpu);
+ StringRef getLibDeviceFile(StringRef Gpu) const {
+ auto Loc = LibDeviceMap.find(Gpu);
+ if (Loc == LibDeviceMap.end())
+ return "";
+ return Loc->second;
}
void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
@@ -226,7 +279,7 @@ public:
void detectHIPRuntime();
/// Get the values for --rocm-device-lib-path arguments
- std::vector<std::string> getRocmDeviceLibPathArg() const {
+ ArrayRef<std::string> getRocmDeviceLibPathArg() const {
return RocmDeviceLibPathArg;
}
@@ -236,7 +289,7 @@ public:
/// Get the value for --hip-version argument
StringRef getHIPVersionArg() const { return HIPVersionArg; }
- std::string getHIPVersion() const { return DetectedVersion; }
+ StringRef getHIPVersion() const { return DetectedVersion; }
};
} // end namespace driver
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/SPIRV.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/SPIRV.cpp
new file mode 100644
index 000000000000..27de69550853
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/SPIRV.cpp
@@ -0,0 +1,93 @@
+//===--- 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::toolchains;
+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-tools-dis");
+
+ 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], {});
+}
+
+clang::driver::Tool *SPIRVToolChain::getTranslator() const {
+ if (!Translator)
+ Translator = std::make_unique<SPIRV::Translator>(*this);
+ return Translator.get();
+}
+
+clang::driver::Tool *SPIRVToolChain::SelectTool(const JobAction &JA) const {
+ Action::ActionClass AC = JA.getKind();
+ return SPIRVToolChain::getTool(AC);
+}
+
+clang::driver::Tool *SPIRVToolChain::getTool(Action::ActionClass AC) const {
+ switch (AC) {
+ default:
+ break;
+ case Action::BackendJobClass:
+ case Action::AssembleJobClass:
+ return SPIRVToolChain::getTranslator();
+ }
+ return ToolChain::getTool(AC);
+}
+clang::driver::Tool *SPIRVToolChain::buildLinker() const {
+ return new tools::SPIRV::Linker(*this);
+}
+
+void SPIRV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const ToolChain &ToolChain = getToolChain();
+ std::string Linker = ToolChain.GetProgramPath(getShortName());
+ ArgStringList CmdArgs;
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Args.MakeArgString(Linker), CmdArgs,
+ Inputs, Output));
+}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/SPIRV.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/SPIRV.h
new file mode 100644
index 000000000000..d4247ee0557f
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/SPIRV.h
@@ -0,0 +1,89 @@
+//===--- 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 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;
+};
+
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
+public:
+ Linker(const ToolChain &TC) : Tool("SPIRV::Linker", "spirv-link", 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;
+};
+
+} // namespace SPIRV
+} // namespace tools
+
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY SPIRVToolChain final : public ToolChain {
+ mutable std::unique_ptr<Tool> Translator;
+
+public:
+ SPIRVToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args)
+ : ToolChain(D, Triple, Args) {}
+
+ bool useIntegratedAs() const override { return true; }
+
+ bool IsIntegratedBackendDefault() const override { return false; }
+ bool IsNonIntegratedBackendSupported() const override { return true; }
+ bool IsMathErrnoDefault() const override { return false; }
+ bool isCrossCompiling() const override { return true; }
+ bool isPICDefault() const override { return false; }
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override {
+ return false;
+ }
+ bool isPICDefaultForced() const override { return false; }
+ bool SupportsProfiling() const override { return false; }
+
+ clang::driver::Tool *SelectTool(const JobAction &JA) const override;
+
+protected:
+ clang::driver::Tool *getTool(Action::ActionClass AC) const override;
+ Tool *buildLinker() const override;
+
+private:
+ clang::driver::Tool *getTranslator() const;
+};
+
+} // namespace toolchains
+} // namespace driver
+} // namespace clang
+#endif
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Solaris.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Solaris.cpp
index 4d1af094f481..200ac46aa534 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Solaris.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Solaris.cpp
@@ -8,12 +8,16 @@
#include "Solaris.h"
#include "CommonArgs.h"
+#include "Gnu.h"
#include "clang/Basic/LangStandard.h"
#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
+#include "clang/Driver/SanitizerArgs.h"
+#include "clang/Driver/ToolChain.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -29,20 +33,50 @@ void solaris::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
- claimNoWarnArgs(Args);
- ArgStringList CmdArgs;
+ // Just call the Gnu version, which enforces gas on Solaris.
+ gnutools::Assembler::ConstructJob(C, JA, Output, Inputs, Args, LinkingOutput);
+}
- Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
+bool solaris::isLinkerGnuLd(const ToolChain &TC, const ArgList &Args) {
+ // Only used if targetting Solaris.
+ const Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ);
+ StringRef UseLinker = A ? A->getValue() : CLANG_DEFAULT_LINKER;
+ return UseLinker == "bfd" || UseLinker == "gld";
+}
- CmdArgs.push_back("-o");
- CmdArgs.push_back(Output.getFilename());
+static bool getPIE(const ArgList &Args, const ToolChain &TC) {
+ if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_static) ||
+ Args.hasArg(options::OPT_r))
+ return false;
- for (const auto &II : Inputs)
- CmdArgs.push_back(II.getFilename());
+ return Args.hasFlag(options::OPT_pie, options::OPT_no_pie,
+ TC.isPIEDefault(Args));
+}
- const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
- C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
- Exec, CmdArgs, Inputs, Output));
+// FIXME: Need to handle CLANG_DEFAULT_LINKER here?
+std::string solaris::Linker::getLinkerPath(const ArgList &Args) const {
+ const ToolChain &ToolChain = getToolChain();
+ if (const Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
+ StringRef UseLinker = A->getValue();
+ if (!UseLinker.empty()) {
+ if (llvm::sys::path::is_absolute(UseLinker) &&
+ llvm::sys::fs::can_execute(UseLinker))
+ return std::string(UseLinker);
+
+ // Accept 'bfd' and 'gld' as aliases for the GNU linker.
+ if (UseLinker == "bfd" || UseLinker == "gld")
+ // FIXME: Could also use /usr/bin/gld here.
+ return "/usr/gnu/bin/ld";
+
+ // Accept 'ld' as alias for the default linker
+ if (UseLinker != "ld")
+ ToolChain.getDriver().Diag(diag::err_drv_invalid_linker_name)
+ << A->getAsString(Args);
+ }
+ }
+
+ // getDefaultLinker() always returns an absolute path.
+ return ToolChain.getDefaultLinker();
}
void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -50,24 +84,38 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
+ const auto &ToolChain = static_cast<const Solaris &>(getToolChain());
+ const Driver &D = ToolChain.getDriver();
+ const llvm::Triple::ArchType Arch = ToolChain.getArch();
+ const bool IsPIE = getPIE(Args, ToolChain);
+ const bool LinkerIsGnuLd = isLinkerGnuLd(ToolChain, Args);
ArgStringList CmdArgs;
- // Demangle C++ names in errors
- CmdArgs.push_back("-C");
+ // Demangle C++ names in errors. GNU ld already defaults to --demangle.
+ if (!LinkerIsGnuLd)
+ CmdArgs.push_back("-C");
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared,
+ options::OPT_r)) {
CmdArgs.push_back("-e");
CmdArgs.push_back("_start");
}
+ if (IsPIE) {
+ if (LinkerIsGnuLd) {
+ CmdArgs.push_back("-pie");
+ } else {
+ CmdArgs.push_back("-z");
+ CmdArgs.push_back("type=pie");
+ }
+ }
+
if (Args.hasArg(options::OPT_static)) {
CmdArgs.push_back("-Bstatic");
CmdArgs.push_back("-dn");
} else {
- CmdArgs.push_back("-Bdynamic");
- if (Args.hasArg(options::OPT_shared)) {
+ if (!Args.hasArg(options::OPT_r) && Args.hasArg(options::OPT_shared))
CmdArgs.push_back("-shared");
- }
// libpthread has been folded into libc since Solaris 10, no need to do
// anything for pthreads. Claim argument to avoid warning.
@@ -75,19 +123,50 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.ClaimAllArgs(options::OPT_pthreads);
}
+ if (LinkerIsGnuLd) {
+ // Set the correct linker emulation for 32- and 64-bit Solaris.
+ switch (Arch) {
+ case llvm::Triple::x86:
+ CmdArgs.push_back("-m");
+ CmdArgs.push_back("elf_i386_sol2");
+ break;
+ case llvm::Triple::x86_64:
+ CmdArgs.push_back("-m");
+ CmdArgs.push_back("elf_x86_64_sol2");
+ break;
+ case llvm::Triple::sparc:
+ CmdArgs.push_back("-m");
+ CmdArgs.push_back("elf32_sparc_sol2");
+ break;
+ case llvm::Triple::sparcv9:
+ CmdArgs.push_back("-m");
+ CmdArgs.push_back("elf64_sparc_sol2");
+ break;
+ default:
+ break;
+ }
+
+ if (Args.hasArg(options::OPT_rdynamic))
+ CmdArgs.push_back("-export-dynamic");
+
+ CmdArgs.push_back("--eh-frame-hdr");
+ } else {
+ // -rdynamic is a no-op with Solaris ld. Claim argument to avoid warning.
+ Args.ClaimAllArgs(options::OPT_rdynamic);
+ }
+
+ assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- } else {
- assert(Output.isNothing() && "Invalid output.");
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
if (!Args.hasArg(options::OPT_shared))
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt1.o")));
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
const Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi);
bool HaveAnsi = false;
@@ -102,29 +181,54 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// Use values-Xc.o for -ansi, -std=c*, -std=iso9899:199409.
if (HaveAnsi || (LangStd && !LangStd->isGNUMode()))
values_X = "values-Xc.o";
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(values_X)));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(values_X)));
const char *values_xpg = "values-xpg6.o";
// Use values-xpg4.o for -std=c90, -std=gnu90, -std=iso9899:199409.
if (LangStd && LangStd->getLanguage() == Language::C && !LangStd->isC99())
values_xpg = "values-xpg4.o";
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath(values_xpg)));
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(values_xpg)));
+
+ const char *crtbegin = nullptr;
+ if (Args.hasArg(options::OPT_shared) || IsPIE)
+ crtbegin = "crtbeginS.o";
+ else
+ crtbegin = "crtbegin.o";
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
+ // Add crtfastmath.o if available and fast math is enabled.
+ ToolChain.addFastMathRuntimeIfAvailable(Args, CmdArgs);
}
- getToolChain().AddFilePathLibArgs(Args, CmdArgs);
+ ToolChain.AddFilePathLibArgs(Args, CmdArgs);
+
+ Args.addAllArgs(CmdArgs,
+ {options::OPT_L, options::OPT_T_Group, options::OPT_r});
- Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
- options::OPT_e, options::OPT_r});
+ bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
- bool NeedsSanitizerDeps = addSanitizerRuntimes(getToolChain(), Args, CmdArgs);
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
+ options::OPT_r)) {
+ // Use the static OpenMP runtime with -static-openmp
+ bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) &&
+ !Args.hasArg(options::OPT_static);
+ addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP);
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
- if (getToolChain().ShouldLinkCXXStdlib(Args))
- getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (D.CCCIsCXX()) {
+ if (ToolChain.ShouldLinkCXXStdlib(Args))
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ CmdArgs.push_back("-lm");
+ }
+ // Silence warnings when linking C code with a C++ '-stdlib' argument.
+ Args.ClaimAllArgs(options::OPT_stdlib_EQ);
+ // Additional linker set-up and flags for Fortran. This is required in order
+ // to generate executables. As Fortran runtime depends on the C runtime,
+ // these dependencies need to be listed before the C runtime below.
+ if (D.IsFlangMode()) {
+ addFortranRuntimeLibraryPath(getToolChain(), Args, CmdArgs);
+ addFortranRuntimeLibs(getToolChain(), Args, CmdArgs);
+ CmdArgs.push_back("-lm");
+ }
if (Args.hasArg(options::OPT_fstack_protector) ||
Args.hasArg(options::OPT_fstack_protector_strong) ||
Args.hasArg(options::OPT_fstack_protector_all)) {
@@ -132,25 +236,57 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lssp_nonshared");
CmdArgs.push_back("-lssp");
}
+ // LLVM support for atomics on 32-bit SPARC V8+ is incomplete, so
+ // forcibly link with libatomic as a workaround.
+ if (Arch == llvm::Triple::sparc) {
+ addAsNeededOption(ToolChain, Args, CmdArgs, true);
+ CmdArgs.push_back("-latomic");
+ addAsNeededOption(ToolChain, Args, CmdArgs, false);
+ }
+ addAsNeededOption(ToolChain, Args, CmdArgs, true);
CmdArgs.push_back("-lgcc_s");
+ addAsNeededOption(ToolChain, Args, CmdArgs, false);
CmdArgs.push_back("-lc");
if (!Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-lgcc");
- CmdArgs.push_back("-lm");
}
- if (NeedsSanitizerDeps)
- linkSanitizerRuntimeDeps(getToolChain(), CmdArgs);
+ const SanitizerArgs &SA = ToolChain.getSanitizerArgs(Args);
+ if (NeedsSanitizerDeps) {
+ linkSanitizerRuntimeDeps(ToolChain, Args, CmdArgs);
+
+ // Work around Solaris/amd64 ld bug when calling __tls_get_addr directly.
+ // However, ld -z relax=transtls is available since Solaris 11.2, but not
+ // in Illumos.
+ if (Arch == llvm::Triple::x86_64 &&
+ (SA.needsAsanRt() || SA.needsStatsRt() ||
+ (SA.needsUbsanRt() && !SA.requiresMinimalRuntime())) &&
+ !LinkerIsGnuLd) {
+ CmdArgs.push_back("-z");
+ CmdArgs.push_back("relax=transtls");
+ }
+ }
+ // Avoid AsanInitInternal cycle, Issue #64126.
+ if (ToolChain.getTriple().isX86() && SA.needsSharedRt() &&
+ SA.needsAsanRt()) {
+ CmdArgs.push_back("-z");
+ CmdArgs.push_back("now");
+ }
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
+ const char *crtend = nullptr;
+ if (Args.hasArg(options::OPT_shared) || IsPIE)
+ crtend = "crtendS.o";
+ else
+ crtend = "crtend.o";
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
}
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
- getToolChain().addProfileRTLibs(Args, CmdArgs);
+ ToolChain.addProfileRTLibs(Args, CmdArgs);
- const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
+ const char *Exec = Args.MakeArgString(getLinkerPath(Args));
C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
Exec, CmdArgs, Inputs, Output));
}
@@ -159,13 +295,12 @@ static StringRef getSolarisLibSuffix(const llvm::Triple &Triple) {
switch (Triple.getArch()) {
case llvm::Triple::x86:
case llvm::Triple::sparc:
+ default:
break;
case llvm::Triple::x86_64:
return "/amd64";
case llvm::Triple::sparcv9:
return "/sparcv9";
- default:
- llvm_unreachable("Unsupported architecture");
}
return "";
}
@@ -192,7 +327,7 @@ Solaris::Solaris(const Driver &D, const llvm::Triple &Triple,
// If we are currently running Clang inside of the requested system root,
// add its parent library path to those searched.
- if (StringRef(D.Dir).startswith(D.SysRoot))
+ if (StringRef(D.Dir).starts_with(D.SysRoot))
addPathIfExists(D, D.Dir + "/../lib", Paths);
addPathIfExists(D, D.SysRoot + "/usr/lib" + LibSuffix, Paths);
@@ -200,7 +335,6 @@ Solaris::Solaris(const Driver &D, const llvm::Triple &Triple,
SanitizerMask Solaris::getSupportedSanitizers() const {
const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
- const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
SanitizerMask Res = ToolChain::getSupportedSanitizers();
// FIXME: Omit X86_64 until 64-bit support is figured out.
if (IsX86) {
@@ -208,12 +342,17 @@ SanitizerMask Solaris::getSupportedSanitizers() const {
Res |= SanitizerKind::PointerCompare;
Res |= SanitizerKind::PointerSubtract;
}
- if (IsX86 || IsX86_64)
- Res |= SanitizerKind::Function;
Res |= SanitizerKind::Vptr;
return Res;
}
+const char *Solaris::getDefaultLinker() const {
+ // FIXME: Only handle Solaris ld and GNU ld here.
+ return llvm::StringSwitch<const char *>(CLANG_DEFAULT_LINKER)
+ .Cases("bfd", "gld", "/usr/gnu/bin/ld")
+ .Default("/usr/bin/ld");
+}
+
Tool *Solaris::buildAssembler() const {
return new tools::solaris::Assembler(*this);
}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Solaris.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Solaris.h
index fbac92c2c0f3..9ec83b773da4 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Solaris.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Solaris.h
@@ -17,12 +17,11 @@ namespace clang {
namespace driver {
namespace tools {
-/// solaris -- Directly call Solaris assembler and linker
+/// Directly call Solaris assembler and linker
namespace solaris {
-class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
+class LLVM_LIBRARY_VISIBILITY Assembler final : public gnutools::Assembler {
public:
- Assembler(const ToolChain &TC)
- : Tool("solaris::Assembler", "assembler", TC) {}
+ Assembler(const ToolChain &TC) : gnutools::Assembler(TC) {}
bool hasIntegratedCPP() const override { return false; }
@@ -32,12 +31,15 @@ public:
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+bool isLinkerGnuLd(const ToolChain &TC, const llvm::opt::ArgList &Args);
+
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
public:
Linker(const ToolChain &TC) : Tool("solaris::Linker", "linker", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
+ std::string getLinkerPath(const llvm::opt::ArgList &Args) const;
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
@@ -63,12 +65,8 @@ public:
llvm::opt::ArgStringList &CC1Args) const override;
SanitizerMask getSupportedSanitizers() const override;
- unsigned GetDefaultDwarfVersion() const override { return 2; }
- const char *getDefaultLinker() const override {
- // clang currently uses Solaris ld-only options.
- return "/usr/bin/ld";
- }
+ const char *getDefaultLinker() const override;
protected:
Tool *buildAssembler() const override;
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/TCE.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/TCE.cpp
index 33a81c54bd42..5f4051d31168 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/TCE.cpp
+++ b/contrib/llvm-project/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/contrib/llvm-project/clang/lib/Driver/ToolChains/TCE.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/TCE.h
index 72933dae965e..31a64cfe878a 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/TCE.h
+++ b/contrib/llvm-project/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/contrib/llvm-project/clang/lib/Driver/ToolChains/VEToolchain.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/VEToolchain.cpp
index e28f340f9aad..39529e0b6b35 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/VEToolchain.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/VEToolchain.cpp
@@ -28,18 +28,32 @@ VEToolChain::VEToolChain(const Driver &D, const llvm::Triple &Triple,
getProgramPaths().push_back("/opt/nec/ve/bin");
// ProgramPaths are found via 'PATH' environment variable.
- // default file paths are:
- // ${RESOURCEDIR}/lib/linux/ve (== getArchSpecificLibPath)
- // /lib/../lib64
- // /usr/lib/../lib64
- // ${BINPATH}/../lib
- // /lib
- // /usr/lib
- //
- // These are OK for host, but no go for VE. So, defines them all
- // from scratch here.
+ // Default library paths are following:
+ // ${RESOURCEDIR}/lib/ve-unknown-linux-gnu,
+ // These are OK.
+
+ // Default file paths are following:
+ // ${RESOURCEDIR}/lib/ve-unknown-linux-gnu, (== getArchSpecificLibPaths)
+ // ${RESOURCEDIR}/lib/linux/ve, (== getArchSpecificLibPaths)
+ // /lib/../lib64,
+ // /usr/lib/../lib64,
+ // ${BINPATH}/../lib,
+ // /lib,
+ // /usr/lib,
+ // These are OK for host, but no go for VE.
+
+ // Define file paths from scratch here.
getFilePaths().clear();
- getFilePaths().push_back(getArchSpecificLibPath());
+
+ // Add library directories:
+ // ${BINPATH}/../lib/ve-unknown-linux-gnu, (== getStdlibPath)
+ // ${RESOURCEDIR}/lib/ve-unknown-linux-gnu, (== getArchSpecificLibPaths)
+ // ${RESOURCEDIR}/lib/linux/ve, (== getArchSpecificLibPaths)
+ // ${SYSROOT}/opt/nec/ve/lib,
+ if (std::optional<std::string> Path = getStdlibPath())
+ getFilePaths().push_back(std::move(*Path));
+ for (const auto &Path : getArchSpecificLibPaths())
+ getFilePaths().push_back(Path);
getFilePaths().push_back(computeSysRoot() + "/opt/nec/ve/lib");
}
@@ -53,7 +67,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; }
@@ -113,9 +129,10 @@ void VEToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArrayRef<StringRef> DirVec(Dirs);
addSystemIncludes(DriverArgs, CC1Args, DirVec);
} else {
- SmallString<128> P(getDriver().ResourceDir);
- llvm::sys::path::append(P, "include/c++/v1");
- addSystemInclude(DriverArgs, CC1Args, P);
+ // Add following paths for multiple target installation.
+ // ${INSTALLDIR}/include/ve-unknown-linux-gnu/c++/v1,
+ // ${INSTALLDIR}/include/c++/v1,
+ addLibCxxIncludePaths(DriverArgs, CC1Args);
}
}
@@ -126,7 +143,15 @@ void VEToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
tools::addArchSpecificRPath(*this, Args, CmdArgs);
+ // Add paths for libc++.so and other shared libraries.
+ if (std::optional<std::string> Path = getStdlibPath()) {
+ CmdArgs.push_back("-rpath");
+ CmdArgs.push_back(Args.MakeArgString(*Path));
+ }
+
CmdArgs.push_back("-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back("-lc++abi");
CmdArgs.push_back("-lunwind");
// libc++ requires -lpthread under glibc environment
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/VEToolchain.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/VEToolchain.h
index b330331ca84e..8b9ccaa7fada 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/VEToolchain.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/VEToolchain.h
@@ -26,9 +26,8 @@ protected:
Tool *buildLinker() const override;
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/contrib/llvm-project/clang/lib/Driver/ToolChains/WebAssembly.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/WebAssembly.cpp
index 19f3571e6b38..0b16b660364f 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -8,15 +8,17 @@
#include "WebAssembly.h"
#include "CommonArgs.h"
+#include "Gnu.h"
#include "clang/Basic/Version.h"
#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
+#include "llvm/Option/ArgList.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
-#include "llvm/Option/ArgList.h"
+#include "llvm/Support/VirtualFileSystem.h"
using namespace clang::driver;
using namespace clang::driver::tools;
@@ -42,8 +44,15 @@ std::string wasm::Linker::getLinkerPath(const ArgList &Args) const {
llvm::sys::fs::can_execute(UseLinker))
return std::string(UseLinker);
- // Accept 'lld', and 'ld' as aliases for the default linker
- if (UseLinker != "lld" && UseLinker != "ld")
+ // Interpret 'lld' as explicitly requesting `wasm-ld`, so look for that
+ // linker. Note that for `wasm32-wasip2` this overrides the default linker
+ // of `wasm-component-ld`.
+ if (UseLinker == "lld") {
+ return ToolChain.GetProgramPath("wasm-ld");
+ }
+
+ // Allow 'ld' as an alias for the default linker
+ if (UseLinker != "ld")
ToolChain.getDriver().Diag(diag::err_drv_invalid_linker_name)
<< A->getAsString(Args);
}
@@ -63,7 +72,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");
@@ -71,34 +80,56 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_s))
CmdArgs.push_back("--strip-all");
- Args.AddAllArgs(CmdArgs, options::OPT_L);
- Args.AddAllArgs(CmdArgs, options::OPT_u);
+ // On `wasip2` the default linker is `wasm-component-ld` which wraps the
+ // execution of `wasm-ld`. Find `wasm-ld` and pass it as an argument of where
+ // to find it to avoid it needing to hunt and rediscover or search `PATH` for
+ // where it is.
+ if (llvm::sys::path::stem(Linker).ends_with_insensitive(
+ "wasm-component-ld")) {
+ CmdArgs.push_back("--wasm-ld-path");
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetProgramPath("wasm-ld")));
+ }
+
+ Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u});
+
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
- const char *Crt1 = "crt1.o";
- const char *Entry = NULL;
+ bool IsCommand = true;
+ const char *Crt1;
+ const char *Entry = nullptr;
- // If crt1-command.o exists, it supports new-style commands, so use it.
- // Otherwise, use the old crt1.o. This is a temporary transition measure.
- // Once WASI libc no longer needs to support LLVM versions which lack
- // support for new-style command, it can make crt1.o the same as
- // crt1-command.o. And once LLVM no longer needs to support WASI libc
- // versions before that, it can switch to using crt1-command.o.
- if (ToolChain.GetFilePath("crt1-command.o") != "crt1-command.o")
- Crt1 = "crt1-command.o";
+ // When -shared is specified, use the reactor exec model unless
+ // specified otherwise.
+ if (Args.hasArg(options::OPT_shared))
+ IsCommand = false;
if (const Arg *A = Args.getLastArg(options::OPT_mexec_model_EQ)) {
StringRef CM = A->getValue();
if (CM == "command") {
- // Use default values.
+ IsCommand = true;
} else if (CM == "reactor") {
- Crt1 = "crt1-reactor.o";
- Entry = "_initialize";
+ IsCommand = false;
} else {
ToolChain.getDriver().Diag(diag::err_drv_invalid_argument_to_option)
<< CM << A->getOption().getName();
}
}
+
+ if (IsCommand) {
+ // If crt1-command.o exists, it supports new-style commands, so use it.
+ // Otherwise, use the old crt1.o. This is a temporary transition measure.
+ // Once WASI libc no longer needs to support LLVM versions which lack
+ // support for new-style command, it can make crt1.o the same as
+ // crt1-command.o. And once LLVM no longer needs to support WASI libc
+ // versions before that, it can switch to using crt1-command.o.
+ Crt1 = "crt1.o";
+ if (ToolChain.GetFilePath("crt1-command.o") != "crt1-command.o")
+ Crt1 = "crt1-command.o";
+ } else {
+ Crt1 = "crt1-reactor.o";
+ Entry = "_initialize";
+ }
+
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(Crt1)));
if (Entry) {
@@ -106,6 +137,9 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(Entry));
}
+ if (Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back(Args.MakeArgString("-shared"));
+
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
@@ -124,14 +158,25 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
+ // When optimizing, if wasm-opt is available, run it.
+ std::string WasmOptPath;
+ if (Args.getLastArg(options::OPT_O_Group)) {
+ WasmOptPath = ToolChain.GetProgramPath("wasm-opt");
+ if (WasmOptPath == "wasm-opt") {
+ WasmOptPath = {};
+ }
+ }
+
+ if (!WasmOptPath.empty()) {
+ CmdArgs.push_back("--keep-section=target_features");
+ }
+
C.addCommand(std::make_unique<Command>(JA, *this,
ResponseFileSupport::AtFileCurCP(),
Linker, CmdArgs, Inputs, Output));
- // When optimizing, if wasm-opt is available, run it.
if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
- auto WasmOptPath = getToolChain().GetProgramPath("wasm-opt");
- if (WasmOptPath != "wasm-opt") {
+ if (!WasmOptPath.empty()) {
StringRef OOpt = "s";
if (A->getOption().matches(options::OPT_O4) ||
A->getOption().matches(options::OPT_Ofast))
@@ -143,13 +188,13 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (OOpt != "0") {
const char *WasmOpt = Args.MakeArgString(WasmOptPath);
- ArgStringList CmdArgs;
- CmdArgs.push_back(Output.getFilename());
- CmdArgs.push_back(Args.MakeArgString(llvm::Twine("-O") + OOpt));
- CmdArgs.push_back("-o");
- CmdArgs.push_back(Output.getFilename());
+ ArgStringList OptArgs;
+ OptArgs.push_back(Output.getFilename());
+ OptArgs.push_back(Args.MakeArgString(llvm::Twine("-O") + OOpt));
+ OptArgs.push_back("-o");
+ OptArgs.push_back(Output.getFilename());
C.addCommand(std::make_unique<Command>(
- JA, *this, ResponseFileSupport::AtFileCurCP(), WasmOpt, CmdArgs,
+ JA, *this, ResponseFileSupport::AtFileCurCP(), WasmOpt, OptArgs,
Inputs, Output));
}
}
@@ -193,6 +238,12 @@ WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple,
}
}
+const char *WebAssembly::getDefaultLinker() const {
+ if (getOS() == "wasip2")
+ return "wasm-component-ld";
+ return "wasm-ld";
+}
+
bool WebAssembly::IsMathErrnoDefault() const { return false; }
bool WebAssembly::IsObjCNonFragileABIDefault() const { return true; }
@@ -201,12 +252,12 @@ 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; }
-bool WebAssembly::IsIntegratedAssemblerDefault() const { return true; }
-
bool WebAssembly::hasBlocksRuntime() const { return false; }
// TODO: Support profiling.
@@ -293,21 +344,24 @@ 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)) {
StringRef Opt = A->getValue(0);
- if (Opt.startswith("-emscripten-cxx-exceptions-allowed")) {
+ if (Opt.starts_with("-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 +377,38 @@ void WebAssembly::addClangTargetOptions(const ArgList &DriverArgs,
":noinline"));
}
}
+
+ if (Opt.starts_with("-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");
+ }
}
}
@@ -334,7 +420,11 @@ ToolChain::CXXStdlibType
WebAssembly::GetCXXStdlibType(const ArgList &Args) const {
if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
StringRef Value = A->getValue();
- if (Value != "libc++")
+ if (Value == "libc++")
+ return ToolChain::CST_Libcxx;
+ else if (Value == "libstdc++")
+ return ToolChain::CST_Libstdcxx;
+ else
getDriver().Diag(diag::err_drv_invalid_stdlib_name)
<< A->getAsString(Args);
}
@@ -380,17 +470,18 @@ void WebAssembly::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
void WebAssembly::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
- if (!DriverArgs.hasArg(options::OPT_nostdlibinc) &&
- !DriverArgs.hasArg(options::OPT_nostdincxx)) {
- if (getTriple().getOS() != llvm::Triple::UnknownOS) {
- const std::string MultiarchTriple =
- getMultiarchTriple(getDriver(), getTriple(), getDriver().SysRoot);
- addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/include/" + MultiarchTriple +
- "/c++/v1");
- }
- addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/include/c++/v1");
+
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc, options::OPT_nostdinc,
+ options::OPT_nostdincxx))
+ return;
+
+ switch (GetCXXStdlibType(DriverArgs)) {
+ case ToolChain::CST_Libcxx:
+ addLibCxxIncludePaths(DriverArgs, CC1Args);
+ break;
+ case ToolChain::CST_Libstdcxx:
+ addLibStdCXXIncludePaths(DriverArgs, CC1Args);
+ break;
}
}
@@ -400,10 +491,13 @@ void WebAssembly::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
switch (GetCXXStdlibType(Args)) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back("-lc++abi");
break;
case ToolChain::CST_Libstdcxx:
- llvm_unreachable("invalid stdlib name");
+ CmdArgs.push_back("-lstdc++");
+ break;
}
}
@@ -412,9 +506,86 @@ SanitizerMask WebAssembly::getSupportedSanitizers() const {
if (getTriple().isOSEmscripten()) {
Res |= SanitizerKind::Vptr | SanitizerKind::Leak | SanitizerKind::Address;
}
+ // -fsanitize=function places two words before the function label, which are
+ // -unsupported.
+ Res &= ~SanitizerKind::Function;
return Res;
}
Tool *WebAssembly::buildLinker() const {
return new tools::wasm::Linker(*this);
}
+
+void WebAssembly::addLibCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ const Driver &D = getDriver();
+ std::string SysRoot = computeSysRoot();
+ std::string LibPath = SysRoot + "/include";
+ const std::string MultiarchTriple =
+ getMultiarchTriple(D, getTriple(), SysRoot);
+ bool IsKnownOs = (getTriple().getOS() != llvm::Triple::UnknownOS);
+
+ std::string Version = detectLibcxxVersion(LibPath);
+ if (Version.empty())
+ return;
+
+ // First add the per-target include path if the OS is known.
+ if (IsKnownOs) {
+ std::string TargetDir = LibPath + "/" + MultiarchTriple + "/c++/" + Version;
+ addSystemInclude(DriverArgs, CC1Args, TargetDir);
+ }
+
+ // Second add the generic one.
+ addSystemInclude(DriverArgs, CC1Args, LibPath + "/c++/" + Version);
+}
+
+void WebAssembly::addLibStdCXXIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ // We cannot use GCCInstallationDetector here as the sysroot usually does
+ // not contain a full GCC installation.
+ // Instead, we search the given sysroot for /usr/include/xx, similar
+ // to how we do it for libc++.
+ const Driver &D = getDriver();
+ std::string SysRoot = computeSysRoot();
+ std::string LibPath = SysRoot + "/include";
+ const std::string MultiarchTriple =
+ getMultiarchTriple(D, getTriple(), SysRoot);
+ bool IsKnownOs = (getTriple().getOS() != llvm::Triple::UnknownOS);
+
+ // This is similar to detectLibcxxVersion()
+ std::string Version;
+ {
+ std::error_code EC;
+ Generic_GCC::GCCVersion MaxVersion =
+ Generic_GCC::GCCVersion::Parse("0.0.0");
+ SmallString<128> Path(LibPath);
+ llvm::sys::path::append(Path, "c++");
+ for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(Path, EC), LE;
+ !EC && LI != LE; LI = LI.increment(EC)) {
+ StringRef VersionText = llvm::sys::path::filename(LI->path());
+ if (VersionText[0] != 'v') {
+ auto Version = Generic_GCC::GCCVersion::Parse(VersionText);
+ if (Version > MaxVersion)
+ MaxVersion = Version;
+ }
+ }
+ if (MaxVersion.Major > 0)
+ Version = MaxVersion.Text;
+ }
+
+ if (Version.empty())
+ return;
+
+ // First add the per-target include path if the OS is known.
+ if (IsKnownOs) {
+ std::string TargetDir = LibPath + "/c++/" + Version + "/" + MultiarchTriple;
+ addSystemInclude(DriverArgs, CC1Args, TargetDir);
+ }
+
+ // Second add the generic one.
+ addSystemInclude(DriverArgs, CC1Args, LibPath + "/c++/" + Version);
+ // Third the backward one.
+ addSystemInclude(DriverArgs, CC1Args, LibPath + "/c++/" + Version + "/backward");
+}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/WebAssembly.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/WebAssembly.h
index 8a3f82d9efdf..76e0ca39bd74 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/WebAssembly.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/WebAssembly.h
@@ -18,7 +18,7 @@ namespace driver {
namespace tools {
namespace wasm {
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
public:
explicit Linker(const ToolChain &TC) : Tool("wasm::Linker", "linker", TC) {}
bool isLinkJob() const override { return true; }
@@ -45,12 +45,12 @@ 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;
bool SupportsProfiling() const override;
bool HasNativeLLVMSupport() const override;
+ unsigned GetDefaultDwarfVersion() const override { return 4; }
void
addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
@@ -67,13 +67,22 @@ private:
llvm::opt::ArgStringList &CmdArgs) const override;
SanitizerMask getSupportedSanitizers() const override;
- const char *getDefaultLinker() const override { return "wasm-ld"; }
+ const char *getDefaultLinker() const override;
+
+ CXXStdlibType GetDefaultCXXStdlibType() const override {
+ return ToolChain::CST_Libcxx;
+ }
Tool *buildLinker() const override;
std::string getMultiarchTriple(const Driver &D,
const llvm::Triple &TargetTriple,
StringRef SysRoot) const override;
+
+ void addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+ void addLibStdCXXIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
};
} // end namespace toolchains
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/XCore.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/XCore.cpp
index 5f94f83d3691..c95ebabdd30c 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/XCore.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/XCore.cpp
@@ -63,11 +63,10 @@ void tools::XCore::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const char *LinkingOutput) const {
ArgStringList CmdArgs;
+ assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- } else {
- assert(Output.isNothing() && "Invalid output.");
}
if (Args.hasArg(options::OPT_v))
@@ -102,7 +101,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; }
@@ -128,6 +129,10 @@ void XCoreToolChain::addClangTargetOptions(const ArgList &DriverArgs,
ArgStringList &CC1Args,
Action::OffloadKind) const {
CC1Args.push_back("-nostdsysteminc");
+ // Set `-fno-use-cxa-atexit` to default.
+ if (!DriverArgs.hasFlag(options::OPT_fuse_cxa_atexit,
+ options::OPT_fno_use_cxa_atexit, false))
+ CC1Args.push_back("-fno-use-cxa-atexit");
}
void XCoreToolChain::AddClangCXXStdlibIncludeArgs(
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/XCore.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/XCore.h
index 41dce08454c0..95359a6e2542 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/XCore.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/XCore.h
@@ -20,7 +20,7 @@ namespace XCore {
// For XCore, we do not need to instantiate tools for PreProcess, PreCompile and
// Compile.
// We simply use "clang -cc1" for those actions.
-class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
+class LLVM_LIBRARY_VISIBILITY Assembler final : public Tool {
public:
Assembler(const ToolChain &TC) : Tool("XCore::Assembler", "XCore-as", TC) {}
@@ -31,7 +31,7 @@ public:
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
public:
Linker(const ToolChain &TC) : Tool("XCore::Linker", "XCore-ld", TC) {}
@@ -57,8 +57,9 @@ protected:
Tool *buildLinker() const override;
public:
+ bool IsIntegratedAssemblerDefault() const override { return false; }
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/contrib/llvm-project/clang/lib/Driver/ToolChains/ZOS.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/ZOS.cpp
index f921227076a5..96dbf602e7c1 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/ZOS.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/ZOS.cpp
@@ -11,11 +11,17 @@
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/Support/WithColor.h"
+using namespace clang;
using namespace clang::driver;
+using namespace clang::driver::tools;
using namespace clang::driver::toolchains;
+using namespace llvm;
using namespace llvm::opt;
-using namespace clang;
+using namespace llvm::sys;
ZOS::ZOS(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: ToolChain(D, Triple, Args) {}
@@ -31,3 +37,303 @@ void ZOS::addClangTargetOptions(const ArgList &DriverArgs,
options::OPT_fno_aligned_allocation))
CC1Args.push_back("-faligned-alloc-unavailable");
}
+
+void zos::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
+
+ // Specify assembler output file.
+ assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ }
+
+ // Specify assembler input file.
+ // The system assembler on z/OS takes exactly one input file. The driver is
+ // expected to invoke as(1) separately for each assembler source input file.
+ if (Inputs.size() != 1)
+ llvm_unreachable("Invalid number of input files.");
+ const InputInfo &II = Inputs[0];
+ assert((II.isFilename() || II.isNothing()) && "Invalid input.");
+ if (II.isFilename())
+ CmdArgs.push_back(II.getFilename());
+
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Exec, CmdArgs, Inputs));
+}
+
+static std::string getLEHLQ(const ArgList &Args) {
+ if (Args.hasArg(options::OPT_mzos_hlq_le_EQ)) {
+ Arg *LEHLQArg = Args.getLastArg(options::OPT_mzos_hlq_le_EQ);
+ StringRef HLQ = LEHLQArg->getValue();
+ if (!HLQ.empty())
+ return HLQ.str();
+ }
+ return "CEE";
+}
+
+static std::string getClangHLQ(const ArgList &Args) {
+ if (Args.hasArg(options::OPT_mzos_hlq_clang_EQ)) {
+ Arg *ClangHLQArg = Args.getLastArg(options::OPT_mzos_hlq_clang_EQ);
+ StringRef HLQ = ClangHLQArg->getValue();
+ if (!HLQ.empty())
+ return HLQ.str();
+ }
+ return getLEHLQ(Args);
+}
+
+static std::string getCSSHLQ(const ArgList &Args) {
+ if (Args.hasArg(options::OPT_mzos_hlq_csslib_EQ)) {
+ Arg *CsslibHLQArg = Args.getLastArg(options::OPT_mzos_hlq_csslib_EQ);
+ StringRef HLQ = CsslibHLQArg->getValue();
+ if (!HLQ.empty())
+ return HLQ.str();
+ }
+ return "SYS1";
+}
+
+void zos::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs, const ArgList &Args,
+ const char *LinkingOutput) const {
+ const ZOS &ToolChain = static_cast<const ZOS &>(getToolChain());
+ ArgStringList CmdArgs;
+
+ const bool IsSharedLib =
+ Args.hasFlag(options::OPT_shared, options::OPT_static, false);
+
+ assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ }
+
+ SmallString<128> LinkerOptions;
+ LinkerOptions = "AMODE=";
+ LinkerOptions += "64";
+ LinkerOptions += ",LIST";
+ LinkerOptions += ",DYNAM=DLL";
+ LinkerOptions += ",MSGLEVEL=4";
+ LinkerOptions += ",CASE=MIXED";
+ LinkerOptions += ",REUS=RENT";
+
+ CmdArgs.push_back("-b");
+ CmdArgs.push_back(Args.MakeArgString(LinkerOptions));
+
+ if (!IsSharedLib) {
+ CmdArgs.push_back("-e");
+ CmdArgs.push_back("CELQSTRT");
+
+ CmdArgs.push_back("-O");
+ CmdArgs.push_back("CELQSTRT");
+
+ CmdArgs.push_back("-u");
+ CmdArgs.push_back("CELQMAIN");
+ }
+
+ // Generate side file if -shared option is present.
+ if (IsSharedLib) {
+ StringRef OutputName = Output.getFilename();
+ // Strip away the last file suffix in presence from output name and add
+ // a new .x suffix.
+ size_t Suffix = OutputName.find_last_of('.');
+ const char *SideDeckName =
+ Args.MakeArgString(OutputName.substr(0, Suffix) + ".x");
+ CmdArgs.push_back("-x");
+ CmdArgs.push_back(SideDeckName);
+ } else {
+ // We need to direct side file to /dev/null to suppress linker warning when
+ // the object file contains exported symbols, and -shared or
+ // -Wl,-x<sidedeck>.x is not specified.
+ CmdArgs.push_back("-x");
+ CmdArgs.push_back("/dev/null");
+ }
+
+ // Add archive library search paths.
+ Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u});
+
+ ToolChain.AddFilePathLibArgs(Args, CmdArgs);
+
+ // Specify linker input file(s)
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
+
+ // z/OS tool chain depends on LE data sets and the CSSLIB data set.
+ // These data sets can have different high level qualifiers (HLQs)
+ // as each installation can define them differently.
+
+ std::string LEHLQ = getLEHLQ(Args);
+ std::string CsslibHLQ = getCSSHLQ(Args);
+
+ StringRef ld_env_var = StringRef(getenv("_LD_SYSLIB")).trim();
+ if (ld_env_var.empty()) {
+ CmdArgs.push_back("-S");
+ CmdArgs.push_back(Args.MakeArgString("//'" + LEHLQ + ".SCEEBND2'"));
+ CmdArgs.push_back("-S");
+ CmdArgs.push_back(Args.MakeArgString("//'" + CsslibHLQ + ".CSSLIB'"));
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ ld_env_var = StringRef(getenv("_LD_SIDE_DECKS")).trim();
+ if (ld_env_var.empty()) {
+ CmdArgs.push_back(
+ Args.MakeArgString("//'" + LEHLQ + ".SCEELIB(CELQS001)'"));
+ CmdArgs.push_back(
+ Args.MakeArgString("//'" + LEHLQ + ".SCEELIB(CELQS003)'"));
+ } else {
+ SmallVector<StringRef> ld_side_deck;
+ ld_env_var.split(ld_side_deck, ":");
+ for (StringRef ld_loc : ld_side_deck) {
+ CmdArgs.push_back((ld_loc.str()).c_str());
+ }
+ }
+ }
+ // Link libc++ library
+ if (ToolChain.ShouldLinkCXXStdlib(Args)) {
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ }
+
+ // Specify compiler-rt library path for linker
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
+ AddRunTimeLibs(ToolChain, ToolChain.getDriver(), CmdArgs, Args);
+
+ const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Exec, CmdArgs, Inputs));
+}
+
+ToolChain::RuntimeLibType ZOS::GetDefaultRuntimeLibType() const {
+ return ToolChain::RLT_CompilerRT;
+}
+
+ToolChain::CXXStdlibType ZOS::GetDefaultCXXStdlibType() const {
+ return ToolChain::CST_Libcxx;
+}
+
+void ZOS::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const {
+ switch (GetCXXStdlibType(Args)) {
+ case ToolChain::CST_Libstdcxx:
+ llvm::report_fatal_error("linking libstdc++ is unimplemented on z/OS");
+ break;
+ case ToolChain::CST_Libcxx: {
+ std::string ClangHLQ = getClangHLQ(Args);
+ CmdArgs.push_back(
+ Args.MakeArgString("//'" + ClangHLQ + ".SCEELIB(CRTDQCXE)'"));
+ CmdArgs.push_back(
+ Args.MakeArgString("//'" + ClangHLQ + ".SCEELIB(CRTDQCXS)'"));
+ CmdArgs.push_back(
+ Args.MakeArgString("//'" + ClangHLQ + ".SCEELIB(CRTDQCXP)'"));
+ CmdArgs.push_back(
+ Args.MakeArgString("//'" + ClangHLQ + ".SCEELIB(CRTDQCXA)'"));
+ CmdArgs.push_back(
+ Args.MakeArgString("//'" + ClangHLQ + ".SCEELIB(CRTDQXLA)'"));
+ CmdArgs.push_back(
+ Args.MakeArgString("//'" + ClangHLQ + ".SCEELIB(CRTDQUNW)'"));
+ } break;
+ }
+}
+
+auto ZOS::buildAssembler() const -> Tool * { return new zos::Assembler(*this); }
+
+auto ZOS::buildLinker() const -> Tool * { return new zos::Linker(*this); }
+
+void ZOS::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdinc))
+ return;
+
+ const Driver &D = getDriver();
+
+ // resolve ResourceDir
+ std::string ResourceDir(D.ResourceDir);
+
+ // zos_wrappers must take highest precedence
+
+ // - <clang>/lib/clang/<ver>/include/zos_wrappers
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+ SmallString<128> P(ResourceDir);
+ path::append(P, "include", "zos_wrappers");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+
+ // - <clang>/lib/clang/<ver>/include
+ SmallString<128> P2(ResourceDir);
+ path::append(P2, "include");
+ addSystemInclude(DriverArgs, CC1Args, P2.str());
+ }
+
+ // - /usr/include
+ if (Arg *SysIncludeArg =
+ DriverArgs.getLastArg(options::OPT_mzos_sys_include_EQ)) {
+ StringRef SysInclude = SysIncludeArg->getValue();
+
+ // fall back to the default include path
+ if (!SysInclude.empty()) {
+
+ // -mzos-sys-include opton can have colon separated
+ // list of paths, so we need to parse the value.
+ StringRef PathLE(SysInclude);
+ size_t Colon = PathLE.find(':');
+ if (Colon == StringRef::npos) {
+ addSystemInclude(DriverArgs, CC1Args, PathLE.str());
+ return;
+ }
+
+ while (Colon != StringRef::npos) {
+ SmallString<128> P = PathLE.substr(0, Colon);
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ PathLE = PathLE.substr(Colon + 1);
+ Colon = PathLE.find(':');
+ }
+ if (PathLE.size())
+ addSystemInclude(DriverArgs, CC1Args, PathLE.str());
+
+ return;
+ }
+ }
+
+ addSystemInclude(DriverArgs, CC1Args, "/usr/include");
+}
+
+void ZOS::TryAddIncludeFromPath(llvm::SmallString<128> Path,
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ if (!getVFS().exists(Path)) {
+ if (DriverArgs.hasArg(options::OPT_v))
+ WithColor::warning(errs(), "Clang")
+ << "ignoring nonexistent directory \"" << Path << "\"\n";
+ if (!DriverArgs.hasArg(options::OPT__HASH_HASH_HASH))
+ return;
+ }
+ addSystemInclude(DriverArgs, CC1Args, Path);
+}
+
+void ZOS::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_Libcxx: {
+ // <install>/bin/../include/c++/v1
+ llvm::SmallString<128> InstallBin =
+ llvm::StringRef(getDriver().getInstalledDir());
+ llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1");
+ TryAddIncludeFromPath(InstallBin, DriverArgs, CC1Args);
+ break;
+ }
+ case ToolChain::CST_Libstdcxx:
+ llvm::report_fatal_error(
+ "picking up libstdc++ headers is unimplemented on z/OS");
+ break;
+ }
+}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/ZOS.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/ZOS.h
index cace85d6da77..45204ba0a543 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/ZOS.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/ZOS.h
@@ -14,6 +14,39 @@
namespace clang {
namespace driver {
+namespace tools {
+
+/// Directly call system default assembler and linker.
+namespace zos {
+
+class LLVM_LIBRARY_VISIBILITY Assembler final : public Tool {
+public:
+ Assembler(const ToolChain &TC) : Tool("zos::Assembler", "assembler", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
+public:
+ Linker(const ToolChain &TC) : Tool("zos::Linker", "linker", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
+} // end namespace zos
+} // end namespace tools
+
namespace toolchains {
class LLVM_LIBRARY_VISIBILITY ZOS : public ToolChain {
@@ -23,14 +56,39 @@ 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; }
+ void TryAddIncludeFromPath(llvm::SmallString<128> Path,
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+ 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;
+
+ unsigned GetDefaultDwarfVersion() const override { return 4; }
+ CXXStdlibType GetDefaultCXXStdlibType() const override;
+
+ void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+
+ RuntimeLibType GetDefaultRuntimeLibType() const override;
void addClangTargetOptions(
const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadingKind) const override;
+
+ const char *getDefaultLinker() const override { return "/bin/ld"; }
+
+protected:
+ Tool *buildAssembler() const override;
+ Tool *buildLinker() const override;
};
} // end namespace toolchains