summaryrefslogtreecommitdiff
path: root/clang/lib/Driver
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
committerDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
commitcfca06d7963fa0909f90483b42a6d7d194d01e08 (patch)
tree209fb2a2d68f8f277793fc8df46c753d31bc853b /clang/lib/Driver
parent706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff)
Notes
Diffstat (limited to 'clang/lib/Driver')
-rw-r--r--clang/lib/Driver/Action.cpp7
-rw-r--r--clang/lib/Driver/Compilation.cpp34
-rw-r--r--clang/lib/Driver/Distro.cpp4
-rw-r--r--clang/lib/Driver/Driver.cpp300
-rw-r--r--clang/lib/Driver/Job.cpp80
-rw-r--r--clang/lib/Driver/Multilib.cpp8
-rw-r--r--clang/lib/Driver/SanitizerArgs.cpp293
-rw-r--r--clang/lib/Driver/Tool.cpp9
-rw-r--r--clang/lib/Driver/ToolChain.cpp238
-rw-r--r--clang/lib/Driver/ToolChains/AIX.cpp53
-rw-r--r--clang/lib/Driver/ToolChains/AIX.h7
-rw-r--r--clang/lib/Driver/ToolChains/AMDGPU.cpp483
-rw-r--r--clang/lib/Driver/ToolChains/AMDGPU.h41
-rw-r--r--clang/lib/Driver/ToolChains/AVR.cpp9
-rw-r--r--clang/lib/Driver/ToolChains/AVR.h4
-rw-r--r--clang/lib/Driver/ToolChains/Ananas.cpp8
-rw-r--r--clang/lib/Driver/ToolChains/Ananas.h9
-rw-r--r--clang/lib/Driver/ToolChains/Arch/AArch64.cpp68
-rw-r--r--clang/lib/Driver/ToolChains/Arch/ARM.cpp59
-rw-r--r--clang/lib/Driver/ToolChains/Arch/ARM.h6
-rw-r--r--clang/lib/Driver/ToolChains/Arch/PPC.cpp22
-rw-r--r--clang/lib/Driver/ToolChains/Arch/RISCV.cpp193
-rw-r--r--clang/lib/Driver/ToolChains/Arch/SystemZ.cpp30
-rw-r--r--clang/lib/Driver/ToolChains/Arch/SystemZ.h10
-rw-r--r--clang/lib/Driver/ToolChains/Arch/VE.cpp26
-rw-r--r--clang/lib/Driver/ToolChains/Arch/VE.h33
-rw-r--r--clang/lib/Driver/ToolChains/Arch/X86.cpp44
-rw-r--r--clang/lib/Driver/ToolChains/BareMetal.cpp10
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp763
-rw-r--r--clang/lib/Driver/ToolChains/Clang.h5
-rw-r--r--clang/lib/Driver/ToolChains/CloudABI.cpp7
-rw-r--r--clang/lib/Driver/ToolChains/CloudABI.h4
-rw-r--r--clang/lib/Driver/ToolChains/CommonArgs.cpp344
-rw-r--r--clang/lib/Driver/ToolChains/CommonArgs.h28
-rw-r--r--clang/lib/Driver/ToolChains/CrossWindows.cpp6
-rw-r--r--clang/lib/Driver/ToolChains/CrossWindows.h3
-rw-r--r--clang/lib/Driver/ToolChains/Cuda.cpp242
-rw-r--r--clang/lib/Driver/ToolChains/Cuda.h21
-rw-r--r--clang/lib/Driver/ToolChains/Darwin.cpp448
-rw-r--r--clang/lib/Driver/ToolChains/Darwin.h44
-rw-r--r--clang/lib/Driver/ToolChains/DragonFly.cpp6
-rw-r--r--clang/lib/Driver/ToolChains/DragonFly.h8
-rw-r--r--clang/lib/Driver/ToolChains/Flang.cpp6
-rw-r--r--clang/lib/Driver/ToolChains/FreeBSD.cpp22
-rw-r--r--clang/lib/Driver/ToolChains/FreeBSD.h22
-rw-r--r--clang/lib/Driver/ToolChains/Fuchsia.cpp27
-rw-r--r--clang/lib/Driver/ToolChains/Fuchsia.h3
-rw-r--r--clang/lib/Driver/ToolChains/Gnu.cpp250
-rw-r--r--clang/lib/Driver/ToolChains/Gnu.h52
-rw-r--r--clang/lib/Driver/ToolChains/HIP.cpp404
-rw-r--r--clang/lib/Driver/ToolChains/HIP.h38
-rw-r--r--clang/lib/Driver/ToolChains/Hexagon.cpp122
-rw-r--r--clang/lib/Driver/ToolChains/Hexagon.h18
-rw-r--r--clang/lib/Driver/ToolChains/Hurd.cpp48
-rw-r--r--clang/lib/Driver/ToolChains/Hurd.h4
-rw-r--r--clang/lib/Driver/ToolChains/InterfaceStubs.cpp5
-rw-r--r--clang/lib/Driver/ToolChains/Linux.cpp175
-rw-r--r--clang/lib/Driver/ToolChains/Linux.h13
-rw-r--r--clang/lib/Driver/ToolChains/MSP430.cpp7
-rw-r--r--clang/lib/Driver/ToolChains/MSP430.h7
-rw-r--r--clang/lib/Driver/ToolChains/MSVC.cpp58
-rw-r--r--clang/lib/Driver/ToolChains/MSVC.h12
-rw-r--r--clang/lib/Driver/ToolChains/MinGW.cpp53
-rw-r--r--clang/lib/Driver/ToolChains/MinGW.h8
-rw-r--r--clang/lib/Driver/ToolChains/Minix.cpp6
-rw-r--r--clang/lib/Driver/ToolChains/Minix.h9
-rw-r--r--clang/lib/Driver/ToolChains/MipsLinux.cpp2
-rw-r--r--clang/lib/Driver/ToolChains/Myriad.cpp15
-rw-r--r--clang/lib/Driver/ToolChains/Myriad.h4
-rw-r--r--clang/lib/Driver/ToolChains/NaCl.cpp3
-rw-r--r--clang/lib/Driver/ToolChains/NaCl.h4
-rw-r--r--clang/lib/Driver/ToolChains/NetBSD.cpp6
-rw-r--r--clang/lib/Driver/ToolChains/NetBSD.h9
-rw-r--r--clang/lib/Driver/ToolChains/OpenBSD.cpp6
-rw-r--r--clang/lib/Driver/ToolChains/OpenBSD.h8
-rw-r--r--clang/lib/Driver/ToolChains/PS4CPU.cpp251
-rw-r--r--clang/lib/Driver/ToolChains/PS4CPU.h19
-rw-r--r--clang/lib/Driver/ToolChains/RISCVToolchain.cpp9
-rw-r--r--clang/lib/Driver/ToolChains/RISCVToolchain.h6
-rw-r--r--clang/lib/Driver/ToolChains/ROCm.h228
-rw-r--r--clang/lib/Driver/ToolChains/Solaris.cpp8
-rw-r--r--clang/lib/Driver/ToolChains/VEToolchain.cpp119
-rw-r--r--clang/lib/Driver/ToolChains/VEToolchain.h66
-rw-r--r--clang/lib/Driver/ToolChains/WebAssembly.cpp37
-rw-r--r--clang/lib/Driver/ToolChains/WebAssembly.h5
-rw-r--r--clang/lib/Driver/ToolChains/XCore.cpp6
-rw-r--r--clang/lib/Driver/Types.cpp77
-rw-r--r--clang/lib/Driver/XRayArgs.cpp298
88 files changed, 4304 insertions, 2268 deletions
diff --git a/clang/lib/Driver/Action.cpp b/clang/lib/Driver/Action.cpp
index 0eb4c7257e7a8..2ec063d873be7 100644
--- a/clang/lib/Driver/Action.cpp
+++ b/clang/lib/Driver/Action.cpp
@@ -43,6 +43,8 @@ const char *Action::getClassName(ActionClass AC) {
return "clang-offload-unbundler";
case OffloadWrapperJobClass:
return "clang-offload-wrapper";
+ case StaticLibJobClass:
+ return "static-lib-linker";
}
llvm_unreachable("invalid class");
@@ -415,3 +417,8 @@ void OffloadWrapperJobAction::anchor() {}
OffloadWrapperJobAction::OffloadWrapperJobAction(ActionList &Inputs,
types::ID Type)
: JobAction(OffloadWrapperJobClass, Inputs, Type) {}
+
+void StaticLibJobAction::anchor() {}
+
+StaticLibJobAction::StaticLibJobAction(ActionList &Inputs, types::ID Type)
+ : JobAction(StaticLibJobClass, Inputs, Type) {}
diff --git a/clang/lib/Driver/Compilation.cpp b/clang/lib/Driver/Compilation.cpp
index ba188f5c4083c..05ee5091396b4 100644
--- a/clang/lib/Driver/Compilation.cpp
+++ b/clang/lib/Driver/Compilation.cpp
@@ -76,16 +76,29 @@ Compilation::getArgsForToolChain(const ToolChain *TC, StringRef BoundArch,
*TranslatedArgs, SameTripleAsHost, AllocatedArgs);
}
+ DerivedArgList *NewDAL = nullptr;
if (!OpenMPArgs) {
+ NewDAL = TC->TranslateXarchArgs(*TranslatedArgs, BoundArch,
+ DeviceOffloadKind, &AllocatedArgs);
+ } else {
+ NewDAL = TC->TranslateXarchArgs(*OpenMPArgs, BoundArch, DeviceOffloadKind,
+ &AllocatedArgs);
+ if (!NewDAL)
+ NewDAL = OpenMPArgs;
+ else
+ delete OpenMPArgs;
+ }
+
+ if (!NewDAL) {
Entry = TC->TranslateArgs(*TranslatedArgs, BoundArch, DeviceOffloadKind);
if (!Entry)
Entry = TranslatedArgs;
} else {
- Entry = TC->TranslateArgs(*OpenMPArgs, BoundArch, DeviceOffloadKind);
+ Entry = TC->TranslateArgs(*NewDAL, BoundArch, DeviceOffloadKind);
if (!Entry)
- Entry = OpenMPArgs;
+ Entry = NewDAL;
else
- delete OpenMPArgs;
+ delete NewDAL;
}
// Add allocated arguments to the final DAL.
@@ -172,7 +185,7 @@ int Compilation::ExecuteCommand(const Command &C,
}
if (getDriver().CCPrintOptions)
- *OS << "[Logging clang options]";
+ *OS << "[Logging clang options]\n";
C.Print(*OS, "\n", /*Quote=*/getDriver().CCPrintOptions);
}
@@ -258,14 +271,23 @@ void Compilation::initCompilationForDiagnostics() {
// Remove any user specified output. Claim any unclaimed arguments, so as
// to avoid emitting warnings about unused args.
- OptSpecifier OutputOpts[] = { options::OPT_o, options::OPT_MD,
- options::OPT_MMD };
+ OptSpecifier OutputOpts[] = {
+ options::OPT_o, options::OPT_MD, options::OPT_MMD, options::OPT_M,
+ options::OPT_MM, options::OPT_MF, options::OPT_MG, options::OPT_MJ,
+ options::OPT_MQ, options::OPT_MT, options::OPT_MV};
for (unsigned i = 0, e = llvm::array_lengthof(OutputOpts); i != e; ++i) {
if (TranslatedArgs->hasArg(OutputOpts[i]))
TranslatedArgs->eraseArg(OutputOpts[i]);
}
TranslatedArgs->ClaimAllArgs();
+ // Force re-creation of the toolchain Args, otherwise our modifications just
+ // above will have no effect.
+ for (auto Arg : TCArgs)
+ if (Arg.second != TranslatedArgs)
+ delete Arg.second;
+ TCArgs.clear();
+
// Redirect stdout/stderr to /dev/null.
Redirects = {None, {""}, {""}};
diff --git a/clang/lib/Driver/Distro.cpp b/clang/lib/Driver/Distro.cpp
index 06707fefc9d08..4d58ad1ae78c6 100644
--- a/clang/lib/Driver/Distro.cpp
+++ b/clang/lib/Driver/Distro.cpp
@@ -11,9 +11,10 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/ADT/Triple.h"
using namespace clang::driver;
using namespace clang;
@@ -70,6 +71,7 @@ static Distro::DistroType DetectDistro(llvm::vfs::FileSystem &VFS,
.Case("disco", Distro::UbuntuDisco)
.Case("eoan", Distro::UbuntuEoan)
.Case("focal", Distro::UbuntuFocal)
+ .Case("groovy", Distro::UbuntuGroovy)
.Default(Distro::UnknownDistro);
if (Version != Distro::UnknownDistro)
return Version;
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index e718b8366df0e..ece8222dcf24f 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -38,11 +38,12 @@
#include "ToolChains/NaCl.h"
#include "ToolChains/NetBSD.h"
#include "ToolChains/OpenBSD.h"
-#include "ToolChains/PS4CPU.h"
#include "ToolChains/PPCLinux.h"
+#include "ToolChains/PS4CPU.h"
#include "ToolChains/RISCVToolchain.h"
#include "ToolChains/Solaris.h"
#include "ToolChains/TCE.h"
+#include "ToolChains/VEToolchain.h"
#include "ToolChains/WebAssembly.h"
#include "ToolChains/XCore.h"
#include "clang/Basic/Version.h"
@@ -71,6 +72,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/Host.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
@@ -99,7 +101,7 @@ std::string Driver::GetResourcesPath(StringRef BinaryPath,
// exact same string ("a/../b/" and "b/" get different hashes, for example).
// Dir is bin/ or lib/, depending on where BinaryPath is.
- std::string Dir = llvm::sys::path::parent_path(BinaryPath);
+ std::string Dir = std::string(llvm::sys::path::parent_path(BinaryPath));
SmallString<128> P(Dir);
if (CustomResourceDir != "") {
@@ -115,7 +117,7 @@ std::string Driver::GetResourcesPath(StringRef BinaryPath,
CLANG_VERSION_STRING);
}
- return P.str();
+ return std::string(P.str());
}
Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple,
@@ -131,15 +133,21 @@ Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple,
TargetTriple(TargetTriple), CCCGenericGCCName(""), Saver(Alloc),
CheckInputsExist(true), GenReproducer(false),
SuppressMissingInputWarning(false) {
-
// Provide a sane fallback if no VFS is specified.
if (!this->VFS)
this->VFS = llvm::vfs::getRealFileSystem();
- Name = llvm::sys::path::filename(ClangExecutable);
- Dir = llvm::sys::path::parent_path(ClangExecutable);
+ Name = std::string(llvm::sys::path::filename(ClangExecutable));
+ Dir = std::string(llvm::sys::path::parent_path(ClangExecutable));
InstalledDir = Dir; // Provide a sensible default installed dir.
+ if ((!SysRoot.empty()) && llvm::sys::path::is_relative(SysRoot)) {
+ // Prepend InstalledDir if SysRoot is relative
+ SmallString<128> P(InstalledDir);
+ llvm::sys::path::append(P, SysRoot);
+ SysRoot = std::string(P);
+ }
+
#if defined(CLANG_CONFIG_FILE_SYSTEM_DIR)
SystemConfigDir = CLANG_CONFIG_FILE_SYSTEM_DIR;
#endif
@@ -467,6 +475,26 @@ static llvm::Triple computeTargetTriple(const Driver &D,
Target.getOS() == llvm::Triple::Minix)
return Target;
+ // On AIX, the env OBJECT_MODE may affect the resulting arch variant.
+ if (Target.isOSAIX()) {
+ if (Optional<std::string> ObjectModeValue =
+ llvm::sys::Process::GetEnv("OBJECT_MODE")) {
+ StringRef ObjectMode = *ObjectModeValue;
+ llvm::Triple::ArchType AT = llvm::Triple::UnknownArch;
+
+ if (ObjectMode.equals("64")) {
+ AT = Target.get64BitArchVariant().getArch();
+ } else if (ObjectMode.equals("32")) {
+ AT = Target.get32BitArchVariant().getArch();
+ } else {
+ D.Diag(diag::err_drv_invalid_object_mode) << ObjectMode;
+ }
+
+ if (AT != llvm::Triple::UnknownArch && AT != Target.getArch())
+ Target.setArch(AT);
+ }
+ }
+
// Handle pseudo-target flags '-m64', '-mx32', '-m32' and '-m16'.
Arg *A = Args.getLastArg(options::OPT_m64, options::OPT_mx32,
options::OPT_m32, options::OPT_m16);
@@ -769,7 +797,7 @@ bool Driver::readConfigFile(StringRef FileName) {
// Read options from config file.
llvm::SmallString<128> CfgFileName(FileName);
llvm::sys::path::native(CfgFileName);
- ConfigFile = CfgFileName.str();
+ ConfigFile = std::string(CfgFileName.str());
bool ContainErrors;
CfgOptions = std::make_unique<InputArgList>(
ParseArgStrings(NewCfgArgs, IsCLMode(), ContainErrors));
@@ -826,8 +854,12 @@ bool Driver::loadConfigFile() {
std::vector<std::string> ConfigFiles =
CLOptions->getAllArgValues(options::OPT_config);
if (ConfigFiles.size() > 1) {
- Diag(diag::err_drv_duplicate_config);
- return true;
+ if (!std::all_of(
+ ConfigFiles.begin(), ConfigFiles.end(),
+ [ConfigFiles](std::string s) { return s == ConfigFiles[0]; })) {
+ Diag(diag::err_drv_duplicate_config);
+ return true;
+ }
}
if (!ConfigFiles.empty()) {
@@ -952,7 +984,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
while (!CompilerPath.empty()) {
std::pair<StringRef, StringRef> Split =
CompilerPath.split(llvm::sys::EnvPathSeparator);
- PrefixDirs.push_back(Split.first);
+ PrefixDirs.push_back(std::string(Split.first));
CompilerPath = Split.second;
}
}
@@ -1035,6 +1067,10 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// -no-canonical-prefixes is used very early in main.
Args.ClaimAllArgs(options::OPT_no_canonical_prefixes);
+ // f(no-)integated-cc1 is also used very early in main.
+ Args.ClaimAllArgs(options::OPT_fintegrated_cc1);
+ Args.ClaimAllArgs(options::OPT_fno_integrated_cc1);
+
// Ignore -pipe.
Args.ClaimAllArgs(options::OPT_pipe);
@@ -1152,7 +1188,7 @@ static void printArgList(raw_ostream &OS, const llvm::opt::ArgList &Args) {
for (auto I = ASL.begin(), E = ASL.end(); I != E; ++I) {
if (I != ASL.begin())
OS << ' ';
- Command::printArg(OS, *I, true);
+ llvm::sys::printArg(OS, *I, true);
}
OS << '\n';
}
@@ -1263,10 +1299,6 @@ void Driver::generateCompilationDiagnostics(
// Print the version of the compiler.
PrintVersion(C, llvm::errs());
- Diag(clang::diag::note_drv_command_failed_diag_msg)
- << "PLEASE submit a bug report to " BUG_REPORT_URL " and include the "
- "crash backtrace, preprocessed source, and associated run script.";
-
// Suppress driver output and emit preprocessor output to temp file.
Mode = CPPMode;
CCGenDiagnostics = true;
@@ -1409,7 +1441,7 @@ void Driver::generateCompilationDiagnostics(
ScriptOS << "\n# Additional information: " << AdditionalInformation
<< "\n";
if (Report)
- Report->TemporaryFiles.push_back(Script.str());
+ Report->TemporaryFiles.push_back(std::string(Script.str()));
Diag(clang::diag::note_drv_command_failed_diag_msg) << Script;
}
@@ -1444,7 +1476,8 @@ void Driver::setUpResponseFiles(Compilation &C, Command &Cmd) {
// capacity if the tool does not support response files, there is a chance/
// that things will just work without a response file, so we silently just
// skip it.
- if (Cmd.getCreator().getResponseFilesSupport() == Tool::RF_None ||
+ if (Cmd.getResponseFileSupport().ResponseKind ==
+ ResponseFileSupport::RF_None ||
llvm::sys::commandLineFitsWithinSystemLimits(Cmd.getExecutable(),
Cmd.getArguments()))
return;
@@ -1638,7 +1671,7 @@ void Driver::HandleAutocompletions(StringRef PassedFlags) const {
// this code.
for (StringRef S : DiagnosticIDs::getDiagnosticFlags())
if (S.startswith(Cur))
- SuggestedCompletions.push_back(S);
+ SuggestedCompletions.push_back(std::string(S));
}
// Sort the autocomplete candidates so that shells print them out in a
@@ -1808,6 +1841,11 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
return false;
}
+ if (C.getArgs().hasArg(options::OPT_print_targets)) {
+ llvm::TargetRegistry::printRegisteredTargetsForVersion(llvm::outs());
+ return false;
+ }
+
return true;
}
@@ -1845,6 +1883,7 @@ static unsigned PrintActions1(const Compilation &C, Action *A,
bool IsFirst = true;
OA->doOnEachDependence(
[&](Action *A, const ToolChain *TC, const char *BoundArch) {
+ assert(TC && "Unknown host toolchain");
// E.g. for two CUDA device dependences whose bound arch is sm_20 and
// sm_35 this will generate:
// "cuda-device" (nvptx64-nvidia-cuda:sm_20) {#ID}, "cuda-device"
@@ -1852,13 +1891,9 @@ static unsigned PrintActions1(const Compilation &C, Action *A,
if (!IsFirst)
os << ", ";
os << '"';
- if (TC)
- os << A->getOffloadingKindPrefix();
- else
- os << "host";
+ os << A->getOffloadingKindPrefix();
os << " (";
os << TC->getTriple().normalize();
-
if (BoundArch)
os << ":" << BoundArch;
os << ")";
@@ -2312,8 +2347,11 @@ class OffloadingActionBuilder final {
/// Append top level actions generated by the builder.
virtual void appendTopLevelActions(ActionList &AL) {}
- /// Append linker actions generated by the builder.
- virtual void appendLinkActions(ActionList &AL) {}
+ /// Append linker device actions generated by the builder.
+ virtual void appendLinkDeviceActions(ActionList &AL) {}
+
+ /// Append linker host action generated by the builder.
+ virtual Action* appendLinkHostActions(ActionList &AL) { return nullptr; }
/// Append linker actions generated by the builder.
virtual void appendLinkDependences(OffloadAction::DeviceDependences &DA) {}
@@ -2522,13 +2560,13 @@ class OffloadingActionBuilder final {
std::set<CudaArch> GpuArchs;
bool Error = false;
for (Arg *A : Args) {
- if (!(A->getOption().matches(options::OPT_cuda_gpu_arch_EQ) ||
- A->getOption().matches(options::OPT_no_cuda_gpu_arch_EQ)))
+ if (!(A->getOption().matches(options::OPT_offload_arch_EQ) ||
+ A->getOption().matches(options::OPT_no_offload_arch_EQ)))
continue;
A->claim();
const StringRef ArchStr = A->getValue();
- if (A->getOption().matches(options::OPT_no_cuda_gpu_arch_EQ) &&
+ if (A->getOption().matches(options::OPT_no_offload_arch_EQ) &&
ArchStr == "all") {
GpuArchs.clear();
continue;
@@ -2537,9 +2575,9 @@ class OffloadingActionBuilder final {
if (Arch == CudaArch::UNKNOWN) {
C.getDriver().Diag(clang::diag::err_drv_cuda_bad_gpu_arch) << ArchStr;
Error = true;
- } else if (A->getOption().matches(options::OPT_cuda_gpu_arch_EQ))
+ } else if (A->getOption().matches(options::OPT_offload_arch_EQ))
GpuArchs.insert(Arch);
- else if (A->getOption().matches(options::OPT_no_cuda_gpu_arch_EQ))
+ else if (A->getOption().matches(options::OPT_no_offload_arch_EQ))
GpuArchs.erase(Arch);
else
llvm_unreachable("Unexpected option.");
@@ -2696,9 +2734,7 @@ class OffloadingActionBuilder final {
// backend and assemble phases to output LLVM IR. Except for generating
// non-relocatable device coee, where we generate fat binary for device
// code and pass to host in Backend phase.
- if (CudaDeviceActions.empty() ||
- (CurPhase == phases::Backend && Relocatable) ||
- CurPhase == phases::Assemble)
+ if (CudaDeviceActions.empty())
return ABRT_Success;
assert(((CurPhase == phases::Link && Relocatable) ||
@@ -2715,10 +2751,15 @@ class OffloadingActionBuilder final {
// a fat binary containing all the code objects for different GPU's.
// The fat binary is then an input to the host action.
for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
+ auto BackendAction = C.getDriver().ConstructPhaseAction(
+ C, Args, phases::Backend, CudaDeviceActions[I],
+ AssociatedOffloadKind);
+ auto AssembleAction = C.getDriver().ConstructPhaseAction(
+ C, Args, phases::Assemble, BackendAction, AssociatedOffloadKind);
// Create a link action to link device IR with device library
// and generate ISA.
ActionList AL;
- AL.push_back(CudaDeviceActions[I]);
+ AL.push_back(AssembleAction);
CudaDeviceActions[I] =
C.MakeAction<LinkJobAction>(AL, types::TY_Image);
@@ -2780,17 +2821,45 @@ class OffloadingActionBuilder final {
: ABRT_Success;
}
- void appendLinkDependences(OffloadAction::DeviceDependences &DA) override {
+ void appendLinkDeviceActions(ActionList &AL) override {
+ if (DeviceLinkerInputs.size() == 0)
+ return;
+
+ assert(DeviceLinkerInputs.size() == GpuArchList.size() &&
+ "Linker inputs and GPU arch list sizes do not match.");
+
// Append a new link action for each device.
unsigned I = 0;
for (auto &LI : DeviceLinkerInputs) {
+ // Each entry in DeviceLinkerInputs corresponds to a GPU arch.
auto *DeviceLinkAction =
C.MakeAction<LinkJobAction>(LI, types::TY_Image);
- DA.add(*DeviceLinkAction, *ToolChains[0],
- CudaArchToString(GpuArchList[I]), AssociatedOffloadKind);
+ // Linking all inputs for the current GPU arch.
+ // LI contains all the inputs for the linker.
+ OffloadAction::DeviceDependences DeviceLinkDeps;
+ DeviceLinkDeps.add(*DeviceLinkAction, *ToolChains[0],
+ CudaArchToString(GpuArchList[I]), AssociatedOffloadKind);
+ AL.push_back(C.MakeAction<OffloadAction>(DeviceLinkDeps,
+ DeviceLinkAction->getType()));
++I;
}
+ DeviceLinkerInputs.clear();
+
+ // Create a host object from all the device images by embedding them
+ // in a fat binary.
+ OffloadAction::DeviceDependences DDeps;
+ auto *TopDeviceLinkAction =
+ C.MakeAction<LinkJobAction>(AL, types::TY_Object);
+ DDeps.add(*TopDeviceLinkAction, *ToolChains[0],
+ nullptr, AssociatedOffloadKind);
+
+ // Offload the host object to the host linker.
+ AL.push_back(C.MakeAction<OffloadAction>(DDeps, TopDeviceLinkAction->getType()));
}
+
+ Action* appendLinkHostActions(ActionList &AL) override { return AL.back(); }
+
+ void appendLinkDependences(OffloadAction::DeviceDependences &DA) override {}
};
/// OpenMP action builder. The host bitcode is passed to the device frontend
@@ -2918,7 +2987,7 @@ class OffloadingActionBuilder final {
OpenMPDeviceActions.clear();
}
- void appendLinkActions(ActionList &AL) override {
+ void appendLinkDeviceActions(ActionList &AL) override {
assert(ToolChains.size() == DeviceLinkerInputs.size() &&
"Toolchains and linker inputs sizes do not match.");
@@ -2937,6 +3006,14 @@ class OffloadingActionBuilder final {
DeviceLinkerInputs.clear();
}
+ Action* appendLinkHostActions(ActionList &AL) override {
+ // Create wrapper bitcode from the result of device link actions and compile
+ // it to an object which will be added to the host link command.
+ auto *BC = C.MakeAction<OffloadWrapperJobAction>(AL, types::TY_LLVM_BC);
+ auto *ASM = C.MakeAction<BackendJobAction>(BC, types::TY_PP_Asm);
+ return C.MakeAction<AssembleJobAction>(ASM, types::TY_Object);
+ }
+
void appendLinkDependences(OffloadAction::DeviceDependences &DA) override {}
bool initialize() override {
@@ -3169,17 +3246,20 @@ public:
for (DeviceActionBuilder *SB : SpecializedBuilders) {
if (!SB->isValid())
continue;
- SB->appendLinkActions(DeviceAL);
+ SB->appendLinkDeviceActions(DeviceAL);
}
if (DeviceAL.empty())
return nullptr;
- // Create wrapper bitcode from the result of device link actions and compile
- // it to an object which will be added to the host link command.
- auto *BC = C.MakeAction<OffloadWrapperJobAction>(DeviceAL, types::TY_LLVM_BC);
- auto *ASM = C.MakeAction<BackendJobAction>(BC, types::TY_PP_Asm);
- return C.MakeAction<AssembleJobAction>(ASM, types::TY_Object);
+ // Let builders add host linking actions.
+ Action* HA;
+ for (DeviceActionBuilder *SB : SpecializedBuilders) {
+ if (!SB->isValid())
+ continue;
+ HA = SB->appendLinkHostActions(DeviceAL);
+ }
+ return HA;
}
/// Processes the host linker action. This currently consists of replacing it
@@ -3267,8 +3347,7 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args,
types::ID InputType = I.first;
const Arg *InputArg = I.second;
- llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PL;
- types::getCompilationPhases(InputType, PL);
+ auto PL = types::getCompilationPhases(InputType);
LastPLSize = PL.size();
// If the first step comes after the final phase we are doing as part of
@@ -3313,11 +3392,9 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args,
// Add a separate precompile phase for the compile phase.
if (FinalPhase >= phases::Compile) {
const types::ID HeaderType = lookupHeaderTypeForSourceType(InputType);
- llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PCHPL;
- types::getCompilationPhases(HeaderType, PCHPL);
// Build the pipeline for the pch file.
Action *ClangClPch = C.MakeAction<InputAction>(*InputArg, HeaderType);
- for (phases::ID Phase : PCHPL)
+ for (phases::ID Phase : types::getCompilationPhases(HeaderType))
ClangClPch = ConstructPhaseAction(C, Args, Phase, ClangClPch);
assert(ClangClPch);
Actions.push_back(ClangClPch);
@@ -3400,13 +3477,11 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
types::ID InputType = I.first;
const Arg *InputArg = I.second;
- llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PL;
- types::getCompilationPhases(*this, Args, InputType, PL);
+ auto PL = types::getCompilationPhases(*this, Args, InputType);
if (PL.empty())
continue;
- llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> FullPL;
- types::getCompilationPhases(InputType, FullPL);
+ auto FullPL = types::getCompilationPhases(InputType);
// Build the pipeline for this file.
Action *Current = C.MakeAction<InputAction>(*InputArg, InputType);
@@ -3489,7 +3564,13 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
if (!LinkerInputs.empty()) {
if (Action *Wrapper = OffloadBuilder.makeHostLinkAction())
LinkerInputs.push_back(Wrapper);
- Action *LA = C.MakeAction<LinkJobAction>(LinkerInputs, types::TY_Image);
+ Action *LA;
+ // Check if this Linker Job should emit a static library.
+ if (ShouldEmitStaticLibrary(Args)) {
+ LA = C.MakeAction<StaticLibJobAction>(LinkerInputs, types::TY_Image);
+ } else {
+ LA = C.MakeAction<LinkJobAction>(LinkerInputs, types::TY_Image);
+ }
LA = OffloadBuilder.processHostLinkAction(LA);
Actions.push_back(LA);
}
@@ -3500,15 +3581,9 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
C.MakeAction<IfsMergeJobAction>(MergerInputs, types::TY_Image));
if (Args.hasArg(options::OPT_emit_interface_stubs)) {
- llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PhaseList;
- if (Args.hasArg(options::OPT_c)) {
- llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> CompilePhaseList;
- types::getCompilationPhases(types::TY_IFS_CPP, CompilePhaseList);
- llvm::copy_if(CompilePhaseList, std::back_inserter(PhaseList),
- [&](phases::ID Phase) { return Phase <= phases::Compile; });
- } else {
- types::getCompilationPhases(types::TY_IFS_CPP, PhaseList);
- }
+ auto PhaseList = types::getCompilationPhases(
+ types::TY_IFS_CPP,
+ Args.hasArg(options::OPT_c) ? phases::Compile : phases::LastPhase);
ActionList MergerInputs;
@@ -3670,7 +3745,10 @@ Action *Driver::ConstructPhaseAction(
Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC;
return C.MakeAction<BackendJobAction>(Input, Output);
}
- if (Args.hasArg(options::OPT_emit_llvm)) {
+ if (Args.hasArg(options::OPT_emit_llvm) ||
+ (TargetDeviceOffloadKind == Action::OFK_HIP &&
+ Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
+ false))) {
types::ID Output =
Args.hasArg(options::OPT_S) ? types::TY_LLVM_IR : types::TY_LLVM_BC;
return C.MakeAction<BackendJobAction>(Input, Output);
@@ -3753,6 +3831,11 @@ void Driver::BuildJobs(Compilation &C) const {
/*TargetDeviceOffloadKind*/ Action::OFK_None);
}
+ // If we have more than one job, then disable integrated-cc1 for now.
+ if (C.getJobs().size() > 1)
+ for (auto &J : C.getJobs())
+ J.InProcess = false;
+
// If the user passed -Qunused-arguments or there were errors, don't warn
// about any unused arguments.
if (Diags.hasErrorOccurred() ||
@@ -4585,8 +4668,19 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
// When using both -save-temps and -emit-llvm, use a ".tmp.bc" suffix for
// the unoptimized bitcode so that it does not get overwritten by the ".bc"
// optimized bitcode output.
- if (!AtTopLevel && C.getArgs().hasArg(options::OPT_emit_llvm) &&
- JA.getType() == types::TY_LLVM_BC)
+ auto IsHIPRDCInCompilePhase = [](const JobAction &JA,
+ const llvm::opt::DerivedArgList &Args) {
+ // The relocatable compilation in HIP implies -emit-llvm. Similarly, use a
+ // ".tmp.bc" suffix for the unoptimized bitcode (generated in the compile
+ // phase.)
+ return isa<CompileJobAction>(JA) &&
+ JA.getOffloadingDeviceKind() == Action::OFK_HIP &&
+ Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
+ false);
+ };
+ if (!AtTopLevel && JA.getType() == types::TY_LLVM_BC &&
+ (C.getArgs().hasArg(options::OPT_emit_llvm) ||
+ IsHIPRDCInCompilePhase(JA, C.getArgs())))
Suffixed += ".tmp";
Suffixed += '.';
Suffixed += Suffix;
@@ -4647,7 +4741,7 @@ std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const {
SmallString<128> P(Dir[0] == '=' ? SysRoot + Dir.substr(1) : Dir);
llvm::sys::path::append(P, Name);
if (llvm::sys::fs::exists(Twine(P)))
- return P.str().str();
+ return std::string(P);
}
return None;
};
@@ -4658,17 +4752,17 @@ std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const {
SmallString<128> R(ResourceDir);
llvm::sys::path::append(R, Name);
if (llvm::sys::fs::exists(Twine(R)))
- return R.str();
+ return std::string(R.str());
SmallString<128> P(TC.getCompilerRTPath());
llvm::sys::path::append(P, Name);
if (llvm::sys::fs::exists(Twine(P)))
- return P.str();
+ return std::string(P.str());
SmallString<128> D(Dir);
llvm::sys::path::append(D, "..", Name);
if (llvm::sys::fs::exists(Twine(D)))
- return D.str();
+ return std::string(D.str());
if (auto P = SearchPaths(TC.getLibraryPaths()))
return *P;
@@ -4676,7 +4770,7 @@ std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const {
if (auto P = SearchPaths(TC.getFilePaths()))
return *P;
- return Name;
+ return std::string(Name);
}
void Driver::generatePrefixedToolNames(
@@ -4693,13 +4787,11 @@ void Driver::generatePrefixedToolNames(
}
static bool ScanDirForExecutable(SmallString<128> &Dir,
- ArrayRef<std::string> Names) {
- for (const auto &Name : Names) {
- llvm::sys::path::append(Dir, Name);
- if (llvm::sys::fs::can_execute(Twine(Dir)))
- return true;
- llvm::sys::path::remove_filename(Dir);
- }
+ const std::string &Name) {
+ llvm::sys::path::append(Dir, Name);
+ if (llvm::sys::fs::can_execute(Twine(Dir)))
+ return true;
+ llvm::sys::path::remove_filename(Dir);
return false;
}
@@ -4712,29 +4804,38 @@ std::string Driver::GetProgramPath(StringRef Name, const ToolChain &TC) const {
for (const auto &PrefixDir : PrefixDirs) {
if (llvm::sys::fs::is_directory(PrefixDir)) {
SmallString<128> P(PrefixDir);
- if (ScanDirForExecutable(P, TargetSpecificExecutables))
- return P.str();
+ for (const auto &TargetSpecificExecutable : TargetSpecificExecutables)
+ if (ScanDirForExecutable(P, TargetSpecificExecutable))
+ return std::string(P.str());
} else {
SmallString<128> P((PrefixDir + Name).str());
if (llvm::sys::fs::can_execute(Twine(P)))
- return P.str();
+ return std::string(P.str());
}
}
const ToolChain::path_list &List = TC.getProgramPaths();
- for (const auto &Path : List) {
- SmallString<128> P(Path);
- if (ScanDirForExecutable(P, TargetSpecificExecutables))
- return P.str();
- }
+ for (const auto &TargetSpecificExecutable : TargetSpecificExecutables) {
+ // For each possible name of the tool look for it in
+ // program paths first, then the path.
+ // Higher priority names will be first, meaning that
+ // a higher priority name in the path will be found
+ // instead of a lower priority name in the program path.
+ // E.g. <triple>-gcc on the path will be found instead
+ // of gcc in the program path
+ for (const auto &Path : List) {
+ SmallString<128> P(Path);
+ if (ScanDirForExecutable(P, TargetSpecificExecutable))
+ return std::string(P.str());
+ }
- // If all else failed, search the path.
- for (const auto &TargetSpecificExecutable : TargetSpecificExecutables)
+ // Fall back to the path
if (llvm::ErrorOr<std::string> P =
llvm::sys::findProgramByName(TargetSpecificExecutable))
return *P;
+ }
- return Name;
+ return std::string(Name);
}
std::string Driver::GetTemporaryPath(StringRef Prefix, StringRef Suffix) const {
@@ -4745,7 +4846,7 @@ std::string Driver::GetTemporaryPath(StringRef Prefix, StringRef Suffix) const {
return "";
}
- return Path.str();
+ return std::string(Path.str());
}
std::string Driver::GetTemporaryDirectory(StringRef Prefix) const {
@@ -4756,7 +4857,7 @@ std::string Driver::GetTemporaryDirectory(StringRef Prefix) const {
return "";
}
- return Path.str();
+ return std::string(Path.str());
}
std::string Driver::GetClPchPath(Compilation &C, StringRef BaseName) const {
@@ -4778,7 +4879,7 @@ std::string Driver::GetClPchPath(Compilation &C, StringRef BaseName) const {
Output = BaseName;
llvm::sys::path::replace_extension(Output, ".pch");
}
- return Output.str();
+ return std::string(Output.str());
}
const ToolChain &Driver::getToolChain(const ArgList &Args,
@@ -4835,6 +4936,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
Target.getArch() == llvm::Triple::ppc64le)
TC = std::make_unique<toolchains::PPCLinuxToolChain>(*this, Target,
Args);
+ else if (Target.getArch() == llvm::Triple::ve)
+ TC = std::make_unique<toolchains::VEToolChain>(*this, Target, Args);
+
else
TC = std::make_unique<toolchains::Linux>(*this, Target, Args);
break;
@@ -4848,6 +4952,8 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
TC = std::make_unique<toolchains::Solaris>(*this, Target, Args);
break;
case llvm::Triple::AMDHSA:
+ TC = std::make_unique<toolchains::ROCMToolChain>(*this, Target, Args);
+ break;
case llvm::Triple::AMDPAL:
case llvm::Triple::Mesa3D:
TC = std::make_unique<toolchains::AMDGPUToolChain>(*this, Target, Args);
@@ -4925,6 +5031,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::riscv64:
TC = std::make_unique<toolchains::RISCVToolChain>(*this, Target, Args);
break;
+ case llvm::Triple::ve:
+ TC = std::make_unique<toolchains::VEToolChain>(*this, Target, Args);
+ break;
default:
if (Target.getVendor() == llvm::Triple::Myriad)
TC = std::make_unique<toolchains::MyriadToolChain>(*this, Target,
@@ -4976,6 +5085,13 @@ bool Driver::ShouldUseFlangCompiler(const JobAction &JA) const {
return true;
}
+bool Driver::ShouldEmitStaticLibrary(const ArgList &Args) const {
+ // Only emit static library if the flag is set explicitly.
+ if (Args.hasArg(options::OPT_emit_static_lib))
+ return true;
+ return false;
+}
+
/// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and return the
/// grouped values as integers. Numbers which are not provided are set to 0.
///
diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp
index d57c3a1cdbb89..4808a9f4628d5 100644
--- a/clang/lib/Driver/Job.cpp
+++ b/clang/lib/Driver/Job.cpp
@@ -36,11 +36,11 @@ using namespace clang;
using namespace driver;
Command::Command(const Action &Source, const Tool &Creator,
- const char *Executable,
+ ResponseFileSupport ResponseSupport, const char *Executable,
const llvm::opt::ArgStringList &Arguments,
ArrayRef<InputInfo> Inputs)
- : Source(Source), Creator(Creator), Executable(Executable),
- Arguments(Arguments) {
+ : Source(Source), Creator(Creator), ResponseSupport(ResponseSupport),
+ Executable(Executable), Arguments(Arguments) {
for (const auto &II : Inputs)
if (II.isFilename())
InputFilenames.push_back(II.getFilename());
@@ -100,27 +100,9 @@ static bool skipArgs(const char *Flag, bool HaveCrashVFS, int &SkipNum,
return false;
}
-void Command::printArg(raw_ostream &OS, StringRef Arg, bool Quote) {
- const bool Escape = Arg.find_first_of(" \"\\$") != StringRef::npos;
-
- if (!Quote && !Escape) {
- OS << Arg;
- return;
- }
-
- // Quote and escape. This isn't really complete, but good enough.
- OS << '"';
- for (const auto c : Arg) {
- if (c == '"' || c == '\\' || c == '$')
- OS << '\\';
- OS << c;
- }
- OS << '"';
-}
-
void Command::writeResponseFile(raw_ostream &OS) const {
// In a file list, we only write the set of inputs to the response file
- if (Creator.getResponseFilesSupport() == Tool::RF_FileList) {
+ if (ResponseSupport.ResponseKind == ResponseFileSupport::RF_FileList) {
for (const auto *Arg : InputFileList) {
OS << Arg << '\n';
}
@@ -149,7 +131,7 @@ void Command::buildArgvForResponseFile(
// When not a file list, all arguments are sent to the response file.
// This leaves us to set the argv to a single parameter, requesting the tool
// to read the response file.
- if (Creator.getResponseFilesSupport() != Tool::RF_FileList) {
+ if (ResponseSupport.ResponseKind != ResponseFileSupport::RF_FileList) {
Out.push_back(Executable);
Out.push_back(ResponseFileFlag.c_str());
return;
@@ -167,7 +149,7 @@ void Command::buildArgvForResponseFile(
Out.push_back(Arg);
} else if (FirstInput) {
FirstInput = false;
- Out.push_back(Creator.getResponseFileFlag());
+ Out.push_back(ResponseSupport.ResponseFlag);
Out.push_back(ResponseFile);
}
}
@@ -217,7 +199,7 @@ void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
CrashReportInfo *CrashInfo) const {
// Always quote the exe.
OS << ' ';
- printArg(OS, Executable, /*Quote=*/true);
+ llvm::sys::printArg(OS, Executable, /*Quote=*/true);
ArrayRef<const char *> Args = Arguments;
SmallVector<const char *, 128> ArgsRespFile;
@@ -245,7 +227,7 @@ void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
if (!NewIncFlags.empty()) {
for (auto &F : NewIncFlags) {
OS << ' ';
- printArg(OS, F.c_str(), Quote);
+ llvm::sys::printArg(OS, F.c_str(), Quote);
}
i += NumArgs - 1;
continue;
@@ -259,20 +241,20 @@ void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
// Replace the input file name with the crashinfo's file name.
OS << ' ';
StringRef ShortName = llvm::sys::path::filename(CrashInfo->Filename);
- printArg(OS, ShortName.str(), Quote);
+ llvm::sys::printArg(OS, ShortName.str(), Quote);
continue;
}
}
OS << ' ';
- printArg(OS, Arg, Quote);
+ llvm::sys::printArg(OS, Arg, Quote);
}
if (CrashInfo && HaveCrashVFS) {
OS << ' ';
- printArg(OS, "-ivfsoverlay", Quote);
+ llvm::sys::printArg(OS, "-ivfsoverlay", Quote);
OS << ' ';
- printArg(OS, CrashInfo->VFSPath.str(), Quote);
+ llvm::sys::printArg(OS, CrashInfo->VFSPath.str(), Quote);
// The leftover modules from the crash are stored in
// <name>.cache/vfs/modules
@@ -287,7 +269,7 @@ void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
ModCachePath.append(RelModCacheDir.c_str());
OS << ' ';
- printArg(OS, ModCachePath, Quote);
+ llvm::sys::printArg(OS, ModCachePath, Quote);
}
if (ResponseFile != nullptr) {
@@ -295,7 +277,7 @@ void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
writeResponseFile(OS);
// Avoiding duplicated newline terminator, since FileLists are
// newline-separated.
- if (Creator.getResponseFilesSupport() != Tool::RF_FileList)
+ if (ResponseSupport.ResponseKind != ResponseFileSupport::RF_FileList)
OS << "\n";
OS << " (end of response file)";
}
@@ -305,7 +287,7 @@ void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
void Command::setResponseFile(const char *FileName) {
ResponseFile = FileName;
- ResponseFileFlag = Creator.getResponseFileFlag();
+ ResponseFileFlag = ResponseSupport.ResponseFlag;
ResponseFileFlag += FileName;
}
@@ -345,7 +327,7 @@ int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
// Save the response file in the appropriate encoding
if (std::error_code EC = writeFileWithEncoding(
- ResponseFile, RespContents, Creator.getResponseFileEncoding())) {
+ ResponseFile, RespContents, ResponseSupport.ResponseEncoding)) {
if (ErrMsg)
*ErrMsg = EC.message();
if (ExecutionFailed)
@@ -371,14 +353,30 @@ int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
/*memoryLimit*/ 0, ErrMsg, ExecutionFailed);
}
+CC1Command::CC1Command(const Action &Source, const Tool &Creator,
+ ResponseFileSupport ResponseSupport,
+ const char *Executable,
+ const llvm::opt::ArgStringList &Arguments,
+ ArrayRef<InputInfo> Inputs)
+ : Command(Source, Creator, ResponseSupport, Executable, Arguments, Inputs) {
+ InProcess = true;
+}
+
void CC1Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
CrashReportInfo *CrashInfo) const {
- OS << " (in-process)";
+ if (InProcess)
+ OS << " (in-process)\n";
Command::Print(OS, Terminator, Quote, CrashInfo);
}
-int CC1Command::Execute(ArrayRef<llvm::Optional<StringRef>> /*Redirects*/,
+int CC1Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
std::string *ErrMsg, bool *ExecutionFailed) const {
+ // FIXME: Currently, if there're more than one job, we disable
+ // -fintegrate-cc1. If we're no longer a integrated-cc1 job, fallback to
+ // out-of-process execution. See discussion in https://reviews.llvm.org/D74447
+ if (!InProcess)
+ return Command::Execute(Redirects, ErrMsg, ExecutionFailed);
+
PrintFileNames();
SmallVector<const char *, 128> Argv;
@@ -413,11 +411,13 @@ void CC1Command::setEnvironment(llvm::ArrayRef<const char *> NewEnvironment) {
}
FallbackCommand::FallbackCommand(const Action &Source_, const Tool &Creator_,
+ ResponseFileSupport ResponseSupport,
const char *Executable_,
const llvm::opt::ArgStringList &Arguments_,
ArrayRef<InputInfo> Inputs,
std::unique_ptr<Command> Fallback_)
- : Command(Source_, Creator_, Executable_, Arguments_, Inputs),
+ : Command(Source_, Creator_, ResponseSupport, Executable_, Arguments_,
+ Inputs),
Fallback(std::move(Fallback_)) {}
void FallbackCommand::Print(raw_ostream &OS, const char *Terminator,
@@ -454,9 +454,11 @@ int FallbackCommand::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
}
ForceSuccessCommand::ForceSuccessCommand(
- const Action &Source_, const Tool &Creator_, const char *Executable_,
+ const Action &Source_, const Tool &Creator_,
+ ResponseFileSupport ResponseSupport, const char *Executable_,
const llvm::opt::ArgStringList &Arguments_, ArrayRef<InputInfo> Inputs)
- : Command(Source_, Creator_, Executable_, Arguments_, Inputs) {}
+ : Command(Source_, Creator_, ResponseSupport, Executable_, Arguments_,
+ Inputs) {}
void ForceSuccessCommand::Print(raw_ostream &OS, const char *Terminator,
bool Quote, CrashReportInfo *CrashInfo) const {
diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp
index 303047e05f78d..5dd55553bcb5f 100644
--- a/clang/lib/Driver/Multilib.cpp
+++ b/clang/lib/Driver/Multilib.cpp
@@ -46,7 +46,7 @@ static void normalizePathSegment(std::string &Segment) {
if (seg.front() != '/') {
Segment = "/" + seg.str();
} else {
- Segment = seg;
+ Segment = std::string(seg);
}
}
@@ -60,19 +60,19 @@ Multilib::Multilib(StringRef GCCSuffix, StringRef OSSuffix,
}
Multilib &Multilib::gccSuffix(StringRef S) {
- GCCSuffix = S;
+ GCCSuffix = std::string(S);
normalizePathSegment(GCCSuffix);
return *this;
}
Multilib &Multilib::osSuffix(StringRef S) {
- OSSuffix = S;
+ OSSuffix = std::string(S);
normalizePathSegment(OSSuffix);
return *this;
}
Multilib &Multilib::includeSuffix(StringRef S) {
- IncludeSuffix = S;
+ IncludeSuffix = std::string(S);
normalizePathSegment(IncludeSuffix);
return *this;
}
diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp
index ac9a294ee3fa4..bcc9ffc7ff8f6 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -14,10 +14,10 @@
#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SpecialCaseList.h"
#include "llvm/Support/TargetParser.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <memory>
using namespace clang;
@@ -27,7 +27,8 @@ using namespace llvm::opt;
static const SanitizerMask NeedsUbsanRt =
SanitizerKind::Undefined | SanitizerKind::Integer |
SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
- SanitizerKind::CFI | SanitizerKind::FloatDivideByZero;
+ SanitizerKind::CFI | SanitizerKind::FloatDivideByZero |
+ SanitizerKind::ObjCCast;
static const SanitizerMask NeedsUbsanCxxRt =
SanitizerKind::Vptr | SanitizerKind::CFI;
static const SanitizerMask NotAllowedWithTrap = SanitizerKind::Vptr;
@@ -43,51 +44,53 @@ static const SanitizerMask SupportsCoverage =
SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |
SanitizerKind::MemTag | SanitizerKind::Memory |
SanitizerKind::KernelMemory | SanitizerKind::Leak |
- SanitizerKind::Undefined | SanitizerKind::Integer |
+ SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::Bounds |
SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
SanitizerKind::DataFlow | SanitizerKind::Fuzzer |
SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero |
- SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack;
+ SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack |
+ SanitizerKind::Thread | SanitizerKind::ObjCCast;
static const SanitizerMask RecoverableByDefault =
SanitizerKind::Undefined | SanitizerKind::Integer |
SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
- SanitizerKind::FloatDivideByZero;
+ SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;
static const SanitizerMask Unrecoverable =
SanitizerKind::Unreachable | SanitizerKind::Return;
static const SanitizerMask AlwaysRecoverable =
SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress;
-static const SanitizerMask LegacyFsanitizeRecoverMask =
- SanitizerKind::Undefined | SanitizerKind::Integer;
static const SanitizerMask NeedsLTO = SanitizerKind::CFI;
static const SanitizerMask TrappingSupported =
(SanitizerKind::Undefined & ~SanitizerKind::Vptr) |
SanitizerKind::UnsignedIntegerOverflow | SanitizerKind::ImplicitConversion |
SanitizerKind::Nullability | SanitizerKind::LocalBounds |
- SanitizerKind::CFI | SanitizerKind::FloatDivideByZero;
+ SanitizerKind::CFI | SanitizerKind::FloatDivideByZero |
+ SanitizerKind::ObjCCast;
static const SanitizerMask TrappingDefault = SanitizerKind::CFI;
static const SanitizerMask CFIClasses =
SanitizerKind::CFIVCall | SanitizerKind::CFINVCall |
SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast |
SanitizerKind::CFIUnrelatedCast;
static const SanitizerMask CompatibleWithMinimalRuntime =
- TrappingSupported | SanitizerKind::Scudo | SanitizerKind::ShadowCallStack;
+ TrappingSupported | SanitizerKind::Scudo | SanitizerKind::ShadowCallStack |
+ SanitizerKind::MemTag;
enum CoverageFeature {
CoverageFunc = 1 << 0,
CoverageBB = 1 << 1,
CoverageEdge = 1 << 2,
CoverageIndirCall = 1 << 3,
- CoverageTraceBB = 1 << 4, // Deprecated.
+ CoverageTraceBB = 1 << 4, // Deprecated.
CoverageTraceCmp = 1 << 5,
CoverageTraceDiv = 1 << 6,
CoverageTraceGep = 1 << 7,
- Coverage8bitCounters = 1 << 8, // Deprecated.
+ Coverage8bitCounters = 1 << 8, // Deprecated.
CoverageTracePC = 1 << 9,
CoverageTracePCGuard = 1 << 10,
CoverageNoPrune = 1 << 11,
CoverageInline8bitCounters = 1 << 12,
CoveragePCTable = 1 << 13,
CoverageStackDepth = 1 << 14,
+ CoverageInlineBoolFlag = 1 << 15,
};
/// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
@@ -118,6 +121,19 @@ static std::string describeSanitizeArg(const llvm::opt::Arg *A,
/// Sanitizers set.
static std::string toString(const clang::SanitizerSet &Sanitizers);
+static void validateSpecialCaseListFormat(const Driver &D,
+ std::vector<std::string> &SCLFiles,
+ unsigned MalformedSCLErrorDiagID) {
+ if (SCLFiles.empty())
+ return;
+
+ std::string BLError;
+ std::unique_ptr<llvm::SpecialCaseList> SCL(
+ llvm::SpecialCaseList::create(SCLFiles, D.getVFS(), BLError));
+ if (!SCL.get())
+ D.Diag(MalformedSCLErrorDiagID) << BLError;
+}
+
static void addDefaultBlacklists(const Driver &D, SanitizerMask Kinds,
std::vector<std::string> &BlacklistFiles) {
struct Blacklist {
@@ -142,12 +158,41 @@ static void addDefaultBlacklists(const Driver &D, SanitizerMask Kinds,
clang::SmallString<64> Path(D.ResourceDir);
llvm::sys::path::append(Path, "share", BL.File);
if (D.getVFS().exists(Path))
- BlacklistFiles.push_back(Path.str());
+ BlacklistFiles.push_back(std::string(Path.str()));
else if (BL.Mask == SanitizerKind::CFI)
// If cfi_blacklist.txt cannot be found in the resource dir, driver
// should fail.
D.Diag(clang::diag::err_drv_no_such_file) << Path;
}
+ validateSpecialCaseListFormat(
+ D, BlacklistFiles, clang::diag::err_drv_malformed_sanitizer_blacklist);
+}
+
+/// Parse -f(no-)?sanitize-(coverage-)?(white|black)list argument's values,
+/// diagnosing any invalid file paths and validating special case list format.
+static void parseSpecialCaseListArg(const Driver &D,
+ const llvm::opt::ArgList &Args,
+ std::vector<std::string> &SCLFiles,
+ llvm::opt::OptSpecifier SCLOptionID,
+ llvm::opt::OptSpecifier NoSCLOptionID,
+ unsigned MalformedSCLErrorDiagID) {
+ for (const auto *Arg : Args) {
+ // Match -fsanitize-(coverage-)?(white|black)list.
+ if (Arg->getOption().matches(SCLOptionID)) {
+ Arg->claim();
+ std::string SCLPath = Arg->getValue();
+ if (D.getVFS().exists(SCLPath)) {
+ SCLFiles.push_back(SCLPath);
+ } else {
+ D.Diag(clang::diag::err_drv_no_such_file) << SCLPath;
+ }
+ // Match -fno-sanitize-blacklist.
+ } else if (Arg->getOption().matches(NoSCLOptionID)) {
+ Arg->claim();
+ SCLFiles.clear();
+ }
+ }
+ validateSpecialCaseListFormat(D, SCLFiles, MalformedSCLErrorDiagID);
}
/// Sets group bits for every group that has at least one representative already
@@ -186,16 +231,6 @@ static SanitizerMask parseSanitizeTrapArgs(const Driver &D,
} else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) {
Arg->claim();
TrapRemove |= expandSanitizerGroups(parseArgValues(D, Arg, true));
- } else if (Arg->getOption().matches(
- options::OPT_fsanitize_undefined_trap_on_error)) {
- Arg->claim();
- TrappingKinds |=
- expandSanitizerGroups(SanitizerKind::UndefinedGroup & ~TrapRemove) &
- ~TrapRemove;
- } else if (Arg->getOption().matches(
- options::OPT_fno_sanitize_undefined_trap_on_error)) {
- Arg->claim();
- TrapRemove |= expandSanitizerGroups(SanitizerKind::UndefinedGroup);
}
}
@@ -412,9 +447,11 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
SanitizerKind::Leak | SanitizerKind::Thread |
SanitizerKind::Memory | SanitizerKind::KernelAddress),
std::make_pair(SanitizerKind::SafeStack,
- SanitizerKind::Address | SanitizerKind::HWAddress |
- SanitizerKind::Leak | SanitizerKind::Thread |
- SanitizerKind::Memory | SanitizerKind::KernelAddress),
+ (TC.getTriple().isOSFuchsia() ? SanitizerMask()
+ : SanitizerKind::Leak) |
+ SanitizerKind::Address | SanitizerKind::HWAddress |
+ SanitizerKind::Thread | SanitizerKind::Memory |
+ SanitizerKind::KernelAddress),
std::make_pair(SanitizerKind::KernelHWAddress,
SanitizerKind::Address | SanitizerKind::HWAddress |
SanitizerKind::Leak | SanitizerKind::Thread |
@@ -454,8 +491,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
<< lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto";
}
- if ((Kinds & SanitizerKind::ShadowCallStack) &&
- TC.getTriple().getArch() == llvm::Triple::aarch64 &&
+ if ((Kinds & SanitizerKind::ShadowCallStack) && TC.getTriple().isAArch64() &&
!llvm::AArch64::isX18ReservedByDefault(TC.getTriple()) &&
!Args.hasArg(options::OPT_ffixed_x18)) {
D.Diag(diag::err_drv_argument_only_allowed_with)
@@ -504,18 +540,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
SanitizerMask DiagnosedUnrecoverableKinds;
SanitizerMask DiagnosedAlwaysRecoverableKinds;
for (const auto *Arg : Args) {
- const char *DeprecatedReplacement = nullptr;
- if (Arg->getOption().matches(options::OPT_fsanitize_recover)) {
- DeprecatedReplacement =
- "-fsanitize-recover=undefined,integer' or '-fsanitize-recover=all";
- RecoverableKinds |= expandSanitizerGroups(LegacyFsanitizeRecoverMask);
- Arg->claim();
- } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover)) {
- DeprecatedReplacement = "-fno-sanitize-recover=undefined,integer' or "
- "'-fno-sanitize-recover=all";
- RecoverableKinds &= ~expandSanitizerGroups(LegacyFsanitizeRecoverMask);
- Arg->claim();
- } else if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
+ if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
SanitizerMask Add = parseArgValues(D, Arg, true);
// Report error if user explicitly tries to recover from unrecoverable
// sanitizer.
@@ -544,10 +569,6 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
RecoverableKinds &= ~expandSanitizerGroups(Remove);
Arg->claim();
}
- if (DeprecatedReplacement) {
- D.Diag(diag::warn_drv_deprecated_arg) << Arg->getAsString(Args)
- << DeprecatedReplacement;
- }
}
RecoverableKinds &= Kinds;
RecoverableKinds &= ~Unrecoverable;
@@ -556,39 +577,17 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
RecoverableKinds &= ~TrappingKinds;
// Setup blacklist files.
- // Add default blacklist from resource directory.
- addDefaultBlacklists(D, Kinds, SystemBlacklistFiles);
- // Parse -f(no-)sanitize-blacklist options.
- for (const auto *Arg : Args) {
- if (Arg->getOption().matches(options::OPT_fsanitize_blacklist)) {
- Arg->claim();
- std::string BLPath = Arg->getValue();
- if (D.getVFS().exists(BLPath)) {
- UserBlacklistFiles.push_back(BLPath);
- } else {
- D.Diag(clang::diag::err_drv_no_such_file) << BLPath;
- }
- } else if (Arg->getOption().matches(options::OPT_fno_sanitize_blacklist)) {
- Arg->claim();
- UserBlacklistFiles.clear();
- SystemBlacklistFiles.clear();
- }
- }
- // Validate blacklists format.
- {
- std::string BLError;
- std::unique_ptr<llvm::SpecialCaseList> SCL(
- llvm::SpecialCaseList::create(UserBlacklistFiles, D.getVFS(), BLError));
- if (!SCL.get())
- D.Diag(clang::diag::err_drv_malformed_sanitizer_blacklist) << BLError;
- }
- {
- std::string BLError;
- std::unique_ptr<llvm::SpecialCaseList> SCL(llvm::SpecialCaseList::create(
- SystemBlacklistFiles, D.getVFS(), BLError));
- if (!SCL.get())
- D.Diag(clang::diag::err_drv_malformed_sanitizer_blacklist) << BLError;
- }
+ // Add default blacklist from resource directory for activated sanitizers, and
+ // validate special case lists format.
+ if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_blacklist))
+ addDefaultBlacklists(D, Kinds, SystemBlacklistFiles);
+
+ // Parse -f(no-)?sanitize-blacklist options.
+ // This also validates special case lists format.
+ parseSpecialCaseListArg(D, Args, UserBlacklistFiles,
+ options::OPT_fsanitize_blacklist,
+ options::OPT_fno_sanitize_blacklist,
+ clang::diag::err_drv_malformed_sanitizer_blacklist);
// Parse -f[no-]sanitize-memory-track-origins[=level] options.
if (AllAddedKinds & SanitizerKind::Memory) {
@@ -721,8 +720,9 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
<< "-fsanitize-coverage=trace-pc-guard";
int InsertionPointTypes = CoverageFunc | CoverageBB | CoverageEdge;
- int InstrumentationTypes =
- CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters;
+ int InstrumentationTypes = CoverageTracePC | CoverageTracePCGuard |
+ CoverageInline8bitCounters |
+ CoverageInlineBoolFlag;
if ((CoverageFeatures & InsertionPointTypes) &&
!(CoverageFeatures & InstrumentationTypes)) {
D.Diag(clang::diag::warn_drv_deprecated_arg)
@@ -733,13 +733,29 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// trace-pc w/o func/bb/edge implies edge.
if (!(CoverageFeatures & InsertionPointTypes)) {
if (CoverageFeatures &
- (CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters))
+ (CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters |
+ CoverageInlineBoolFlag))
CoverageFeatures |= CoverageEdge;
if (CoverageFeatures & CoverageStackDepth)
CoverageFeatures |= CoverageFunc;
}
+ // Parse -fsanitize-coverage-(black|white)list options if coverage enabled.
+ // This also validates special case lists format.
+ // Here, OptSpecifier() acts as a never-matching command-line argument.
+ // So, there is no way to clear coverage lists but you can append to them.
+ if (CoverageFeatures) {
+ parseSpecialCaseListArg(
+ D, Args, CoverageAllowlistFiles,
+ options::OPT_fsanitize_coverage_allowlist, OptSpecifier(),
+ clang::diag::err_drv_malformed_sanitizer_coverage_whitelist);
+ parseSpecialCaseListArg(
+ D, Args, CoverageBlocklistFiles,
+ options::OPT_fsanitize_coverage_blocklist, OptSpecifier(),
+ clang::diag::err_drv_malformed_sanitizer_coverage_blacklist);
+ }
+
SharedRuntime =
Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan,
TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() ||
@@ -831,8 +847,9 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
}
if (AllAddedKinds & SanitizerKind::SafeStack) {
- // SafeStack runtime is built into the system on Fuchsia.
- SafeStackRuntime = !TC.getTriple().isOSFuchsia();
+ // SafeStack runtime is built into the system on Android and Fuchsia.
+ SafeStackRuntime =
+ !TC.getTriple().isAndroid() && !TC.getTriple().isOSFuchsia();
}
LinkRuntimes =
@@ -865,6 +882,17 @@ static std::string toString(const clang::SanitizerSet &Sanitizers) {
return Res;
}
+static void addSpecialCaseListOpt(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs,
+ const char *SCLOptFlag,
+ const std::vector<std::string> &SCLFiles) {
+ for (const auto &SCLPath : SCLFiles) {
+ SmallString<64> SCLOpt(SCLOptFlag);
+ SCLOpt += SCLPath;
+ CmdArgs.push_back(Args.MakeArgString(SCLOpt));
+ }
+}
+
static void addIncludeLinkerOption(const ToolChain &TC,
const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
@@ -904,45 +932,55 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
// Do it even if Sanitizers.empty() since some forms of coverage don't require
// sanitizers.
std::pair<int, const char *> CoverageFlags[] = {
- std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"),
- std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"),
- std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"),
- std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"),
- std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"),
- std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"),
- std::make_pair(CoverageTraceDiv, "-fsanitize-coverage-trace-div"),
- std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"),
- std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"),
- std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"),
- std::make_pair(CoverageTracePCGuard, "-fsanitize-coverage-trace-pc-guard"),
- std::make_pair(CoverageInline8bitCounters, "-fsanitize-coverage-inline-8bit-counters"),
- std::make_pair(CoveragePCTable, "-fsanitize-coverage-pc-table"),
- std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune"),
- std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth")};
+ std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"),
+ std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"),
+ std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"),
+ std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"),
+ std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"),
+ std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"),
+ std::make_pair(CoverageTraceDiv, "-fsanitize-coverage-trace-div"),
+ std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"),
+ std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"),
+ std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"),
+ std::make_pair(CoverageTracePCGuard,
+ "-fsanitize-coverage-trace-pc-guard"),
+ std::make_pair(CoverageInline8bitCounters,
+ "-fsanitize-coverage-inline-8bit-counters"),
+ std::make_pair(CoverageInlineBoolFlag,
+ "-fsanitize-coverage-inline-bool-flag"),
+ std::make_pair(CoveragePCTable, "-fsanitize-coverage-pc-table"),
+ std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune"),
+ std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth")};
for (auto F : CoverageFlags) {
if (CoverageFeatures & F.first)
CmdArgs.push_back(F.second);
}
+ addSpecialCaseListOpt(
+ Args, CmdArgs, "-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);
+ addSpecialCaseListOpt(
+ Args, CmdArgs, "-fsanitize-coverage-blocklist=", CoverageBlocklistFiles);
if (TC.getTriple().isOSWindows() && needsUbsanRt()) {
// Instruct the code generator to embed linker directives in the object file
// that cause the required runtime libraries to be linked.
- CmdArgs.push_back(Args.MakeArgString(
- "--dependent-lib=" + TC.getCompilerRT(Args, "ubsan_standalone")));
+ CmdArgs.push_back(
+ Args.MakeArgString("--dependent-lib=" +
+ TC.getCompilerRTBasename(Args, "ubsan_standalone")));
if (types::isCXX(InputType))
CmdArgs.push_back(Args.MakeArgString(
- "--dependent-lib=" + TC.getCompilerRT(Args, "ubsan_standalone_cxx")));
+ "--dependent-lib=" +
+ TC.getCompilerRTBasename(Args, "ubsan_standalone_cxx")));
}
if (TC.getTriple().isOSWindows() && needsStatsRt()) {
- CmdArgs.push_back(Args.MakeArgString("--dependent-lib=" +
- TC.getCompilerRT(Args, "stats_client")));
+ CmdArgs.push_back(Args.MakeArgString(
+ "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats_client")));
// The main executable must export the stats runtime.
// FIXME: Only exporting from the main executable (e.g. based on whether the
// translation unit defines main()) would save a little space, but having
// multiple copies of the runtime shouldn't hurt.
- CmdArgs.push_back(Args.MakeArgString("--dependent-lib=" +
- TC.getCompilerRT(Args, "stats")));
+ CmdArgs.push_back(Args.MakeArgString(
+ "--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats")));
addIncludeLinkerOption(TC, Args, CmdArgs, "__sanitizer_stats_register");
}
@@ -958,16 +996,10 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
CmdArgs.push_back(
Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));
- for (const auto &BLPath : UserBlacklistFiles) {
- SmallString<64> BlacklistOpt("-fsanitize-blacklist=");
- BlacklistOpt += BLPath;
- CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
- }
- for (const auto &BLPath : SystemBlacklistFiles) {
- SmallString<64> BlacklistOpt("-fsanitize-system-blacklist=");
- BlacklistOpt += BLPath;
- CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
- }
+ addSpecialCaseListOpt(Args, CmdArgs,
+ "-fsanitize-blacklist=", UserBlacklistFiles);
+ addSpecialCaseListOpt(Args, CmdArgs,
+ "-fsanitize-system-blacklist=", SystemBlacklistFiles);
if (MsanTrackOrigins)
CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" +
@@ -1038,7 +1070,7 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi));
}
- if (Sanitizers.has(SanitizerKind::HWAddress)) {
+ if (Sanitizers.has(SanitizerKind::HWAddress) && TC.getTriple().isAArch64()) {
CmdArgs.push_back("-target-feature");
CmdArgs.push_back("+tagged-globals");
}
@@ -1102,22 +1134,23 @@ int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A) {
for (int i = 0, n = A->getNumValues(); i != n; ++i) {
const char *Value = A->getValue(i);
int F = llvm::StringSwitch<int>(Value)
- .Case("func", CoverageFunc)
- .Case("bb", CoverageBB)
- .Case("edge", CoverageEdge)
- .Case("indirect-calls", CoverageIndirCall)
- .Case("trace-bb", CoverageTraceBB)
- .Case("trace-cmp", CoverageTraceCmp)
- .Case("trace-div", CoverageTraceDiv)
- .Case("trace-gep", CoverageTraceGep)
- .Case("8bit-counters", Coverage8bitCounters)
- .Case("trace-pc", CoverageTracePC)
- .Case("trace-pc-guard", CoverageTracePCGuard)
- .Case("no-prune", CoverageNoPrune)
- .Case("inline-8bit-counters", CoverageInline8bitCounters)
- .Case("pc-table", CoveragePCTable)
- .Case("stack-depth", CoverageStackDepth)
- .Default(0);
+ .Case("func", CoverageFunc)
+ .Case("bb", CoverageBB)
+ .Case("edge", CoverageEdge)
+ .Case("indirect-calls", CoverageIndirCall)
+ .Case("trace-bb", CoverageTraceBB)
+ .Case("trace-cmp", CoverageTraceCmp)
+ .Case("trace-div", CoverageTraceDiv)
+ .Case("trace-gep", CoverageTraceGep)
+ .Case("8bit-counters", Coverage8bitCounters)
+ .Case("trace-pc", CoverageTracePC)
+ .Case("trace-pc-guard", CoverageTracePCGuard)
+ .Case("no-prune", CoverageNoPrune)
+ .Case("inline-8bit-counters", CoverageInline8bitCounters)
+ .Case("inline-bool-flag", CoverageInlineBoolFlag)
+ .Case("pc-table", CoveragePCTable)
+ .Case("stack-depth", CoverageStackDepth)
+ .Default(0);
if (F == 0)
D.Diag(clang::diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Value;
diff --git a/clang/lib/Driver/Tool.cpp b/clang/lib/Driver/Tool.cpp
index 9ff6e863a1242..449f69cfcb357 100644
--- a/clang/lib/Driver/Tool.cpp
+++ b/clang/lib/Driver/Tool.cpp
@@ -11,13 +11,8 @@
using namespace clang::driver;
-Tool::Tool(const char *_Name, const char *_ShortName, const ToolChain &TC,
- ResponseFileSupport _ResponseSupport,
- llvm::sys::WindowsEncodingMethod _ResponseEncoding,
- const char *_ResponseFlag)
- : Name(_Name), ShortName(_ShortName), TheToolChain(TC),
- ResponseSupport(_ResponseSupport), ResponseEncoding(_ResponseEncoding),
- ResponseFlag(_ResponseFlag) {}
+Tool::Tool(const char *_Name, const char *_ShortName, const ToolChain &TC)
+ : Name(_Name), ShortName(_ShortName), TheToolChain(TC) {}
Tool::~Tool() {
}
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 3ebbd30195b31..b8c12fc9241a6 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -68,8 +68,7 @@ static ToolChain::RTTIMode CalculateRTTIMode(const ArgList &Args,
}
// -frtti is default, except for the PS4 CPU.
- return (Triple.isPS4CPU() || Triple.isNVPTX()) ? ToolChain::RM_Disabled
- : ToolChain::RM_Enabled;
+ return (Triple.isPS4CPU()) ? ToolChain::RM_Disabled : ToolChain::RM_Enabled;
}
ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
@@ -169,7 +168,7 @@ static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {
/// Normalize the program name from argv[0] by stripping the file extension if
/// present and lower-casing the string on Windows.
static std::string normalizeProgramName(llvm::StringRef Argv0) {
- std::string ProgName = llvm::sys::path::stem(Argv0);
+ std::string ProgName = std::string(llvm::sys::path::stem(Argv0));
#ifdef _WIN32
// Transform to lowercase for case insensitive file systems.
std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(), ::tolower);
@@ -222,16 +221,21 @@ ToolChain::getTargetAndModeFromProgramName(StringRef PN) {
StringRef Prefix(ProgName);
Prefix = Prefix.slice(0, LastComponent);
std::string IgnoredError;
- bool IsRegistered = llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError);
- return ParsedClangName{Prefix, ModeSuffix, DS->ModeFlag, IsRegistered};
+ bool IsRegistered =
+ llvm::TargetRegistry::lookupTarget(std::string(Prefix), IgnoredError);
+ return ParsedClangName{std::string(Prefix), ModeSuffix, DS->ModeFlag,
+ IsRegistered};
}
StringRef ToolChain::getDefaultUniversalArchName() const {
// In universal driver terms, the arch name accepted by -arch isn't exactly
// the same as the ones that appear in the triple. Roughly speaking, this is
- // an inverse of the darwin::getArchTypeForDarwinArchName() function, but the
- // only interesting special case is powerpc.
+ // an inverse of the darwin::getArchTypeForDarwinArchName() function.
switch (Triple.getArch()) {
+ case llvm::Triple::aarch64:
+ return "arm64";
+ case llvm::Triple::aarch64_32:
+ return "arm64_32";
case llvm::Triple::ppc:
return "ppc";
case llvm::Triple::ppc64:
@@ -271,6 +275,10 @@ Tool *ToolChain::buildLinker() const {
llvm_unreachable("Linking is not supported by this toolchain");
}
+Tool *ToolChain::buildStaticLibTool() const {
+ llvm_unreachable("Creating static lib is not supported by this toolchain");
+}
+
Tool *ToolChain::getAssemble() const {
if (!Assemble)
Assemble.reset(buildAssembler());
@@ -289,6 +297,12 @@ Tool *ToolChain::getLink() const {
return Link.get();
}
+Tool *ToolChain::getStaticLibTool() const {
+ if (!StaticLibTool)
+ StaticLibTool.reset(buildStaticLibTool());
+ return StaticLibTool.get();
+}
+
Tool *ToolChain::getIfsMerge() const {
if (!IfsMerge)
IfsMerge.reset(new tools::ifstool::Merger(*this));
@@ -318,6 +332,9 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const {
case Action::LinkJobClass:
return getLink();
+ case Action::StaticLibJobClass:
+ return getStaticLibTool();
+
case Action::InputClass:
case Action::BindArchClass:
case Action::OffloadClass:
@@ -386,11 +403,12 @@ std::string ToolChain::getCompilerRTPath() const {
} else {
llvm::sys::path::append(Path, "lib", getOSLibName());
}
- return Path.str();
+ return std::string(Path.str());
}
-std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component,
- FileType Type) const {
+std::string ToolChain::getCompilerRTBasename(const ArgList &Args,
+ StringRef Component, FileType Type,
+ bool AddArch) const {
const llvm::Triple &TT = getTriple();
bool IsITANMSVCWindows =
TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment();
@@ -412,19 +430,33 @@ std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component,
break;
}
+ std::string ArchAndEnv;
+ if (AddArch) {
+ StringRef Arch = getArchNameForCompilerRTLib(*this, Args);
+ const char *Env = TT.isAndroid() ? "-android" : "";
+ ArchAndEnv = ("-" + Arch + Env).str();
+ }
+ return (Prefix + Twine("clang_rt.") + Component + ArchAndEnv + Suffix).str();
+}
+
+std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component,
+ FileType Type) const {
+ // Check for runtime files in the new layout without the architecture first.
+ std::string CRTBasename =
+ getCompilerRTBasename(Args, Component, Type, /*AddArch=*/false);
for (const auto &LibPath : getLibraryPaths()) {
SmallString<128> P(LibPath);
- llvm::sys::path::append(P, Prefix + Twine("clang_rt.") + Component + Suffix);
+ llvm::sys::path::append(P, CRTBasename);
if (getVFS().exists(P))
- return P.str();
+ return std::string(P.str());
}
- StringRef Arch = getArchNameForCompilerRTLib(*this, Args);
- const char *Env = TT.isAndroid() ? "-android" : "";
+ // Fall back to the old expected compiler-rt name if the new one does not
+ // exist.
+ CRTBasename = getCompilerRTBasename(Args, Component, Type, /*AddArch=*/true);
SmallString<128> Path(getCompilerRTPath());
- llvm::sys::path::append(Path, Prefix + Twine("clang_rt.") + Component + "-" +
- Arch + Env + Suffix);
- return Path.str();
+ llvm::sys::path::append(Path, CRTBasename);
+ return std::string(Path.str());
}
const char *ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args,
@@ -441,13 +473,13 @@ Optional<std::string> ToolChain::getRuntimePath() const {
P.assign(D.ResourceDir);
llvm::sys::path::append(P, "lib", D.getTargetTriple());
if (getVFS().exists(P))
- return llvm::Optional<std::string>(P.str());
+ return llvm::Optional<std::string>(std::string(P.str()));
// Second try the normalized triple.
P.assign(D.ResourceDir);
llvm::sys::path::append(P, "lib", Triple.str());
if (getVFS().exists(P))
- return llvm::Optional<std::string>(P.str());
+ return llvm::Optional<std::string>(std::string(P.str()));
return None;
}
@@ -459,13 +491,13 @@ Optional<std::string> ToolChain::getCXXStdlibPath() const {
P.assign(D.Dir);
llvm::sys::path::append(P, "..", "lib", D.getTargetTriple(), "c++");
if (getVFS().exists(P))
- return llvm::Optional<std::string>(P.str());
+ return llvm::Optional<std::string>(std::string(P.str()));
// Second try the normalized triple.
P.assign(D.Dir);
llvm::sys::path::append(P, "..", "lib", Triple.str(), "c++");
if (getVFS().exists(P))
- return llvm::Optional<std::string>(P.str());
+ return llvm::Optional<std::string>(std::string(P.str()));
return None;
}
@@ -474,31 +506,27 @@ std::string ToolChain::getArchSpecificLibPath() const {
SmallString<128> Path(getDriver().ResourceDir);
llvm::sys::path::append(Path, "lib", getOSLibName(),
llvm::Triple::getArchTypeName(getArch()));
- return Path.str();
+ return std::string(Path.str());
}
bool ToolChain::needsProfileRT(const ArgList &Args) {
if (Args.hasArg(options::OPT_noprofilelib))
return false;
- if (needsGCovInstrumentation(Args) ||
- Args.hasArg(options::OPT_fprofile_generate) ||
- Args.hasArg(options::OPT_fprofile_generate_EQ) ||
- Args.hasArg(options::OPT_fcs_profile_generate) ||
- Args.hasArg(options::OPT_fcs_profile_generate_EQ) ||
- Args.hasArg(options::OPT_fprofile_instr_generate) ||
- Args.hasArg(options::OPT_fprofile_instr_generate_EQ) ||
- Args.hasArg(options::OPT_fcreate_profile) ||
- Args.hasArg(options::OPT_forder_file_instrumentation))
- return true;
-
- return false;
+ return Args.hasArg(options::OPT_fprofile_generate) ||
+ Args.hasArg(options::OPT_fprofile_generate_EQ) ||
+ Args.hasArg(options::OPT_fcs_profile_generate) ||
+ Args.hasArg(options::OPT_fcs_profile_generate_EQ) ||
+ Args.hasArg(options::OPT_fprofile_instr_generate) ||
+ Args.hasArg(options::OPT_fprofile_instr_generate_EQ) ||
+ Args.hasArg(options::OPT_fcreate_profile) ||
+ Args.hasArg(options::OPT_forder_file_instrumentation);
}
bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) {
- return Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
- false) ||
- Args.hasArg(options::OPT_coverage);
+ return Args.hasArg(options::OPT_coverage) ||
+ Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
+ false);
}
Tool *ToolChain::SelectTool(const JobAction &JA) const {
@@ -526,7 +554,7 @@ std::string ToolChain::GetLinkerPath() const {
// If we're passed what looks like an absolute path, don't attempt to
// second-guess that.
if (llvm::sys::fs::can_execute(UseLinker))
- return UseLinker;
+ return std::string(UseLinker);
} else if (UseLinker.empty() || UseLinker == "ld") {
// If we're passed -fuse-ld= with no argument, or with the argument ld,
// then use whatever the default system linker is.
@@ -550,6 +578,11 @@ std::string ToolChain::GetLinkerPath() const {
return GetProgramPath(getDefaultLinker());
}
+std::string ToolChain::GetStaticLibToolPath() const {
+ // TODO: Add support for static lib archiving on Windows
+ return GetProgramPath("llvm-ar");
+}
+
types::ID ToolChain::LookupTypeForExtension(StringRef Ext) const {
types::ID id = types::lookupTypeForExtension(Ext);
@@ -735,6 +768,10 @@ std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
return ComputeLLVMTriple(Args, InputType);
}
+std::string ToolChain::computeSysRoot() const {
+ return D.SysRoot;
+}
+
void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
// Each toolchain should provide the appropriate include flags.
@@ -748,7 +785,8 @@ void ToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {}
void ToolChain::addProfileRTLibs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const {
- if (!needsProfileRT(Args)) return;
+ if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args))
+ return;
CmdArgs.push_back(getCompilerRTArgString(Args, "profile"));
}
@@ -916,28 +954,35 @@ void ToolChain::AddCCKextLibArgs(const ArgList &Args,
CmdArgs.push_back("-lcc_kext");
}
-bool ToolChain::AddFastMathRuntimeIfAvailable(const ArgList &Args,
- ArgStringList &CmdArgs) const {
+bool ToolChain::isFastMathRuntimeAvailable(const ArgList &Args,
+ std::string &Path) const {
// Do not check for -fno-fast-math or -fno-unsafe-math when -Ofast passed
// (to keep the linker options consistent with gcc and clang itself).
if (!isOptimizationLevelFast(Args)) {
// Check if -ffast-math or -funsafe-math.
Arg *A =
- Args.getLastArg(options::OPT_ffast_math, options::OPT_fno_fast_math,
- options::OPT_funsafe_math_optimizations,
- options::OPT_fno_unsafe_math_optimizations);
+ Args.getLastArg(options::OPT_ffast_math, options::OPT_fno_fast_math,
+ options::OPT_funsafe_math_optimizations,
+ options::OPT_fno_unsafe_math_optimizations);
if (!A || A->getOption().getID() == options::OPT_fno_fast_math ||
A->getOption().getID() == options::OPT_fno_unsafe_math_optimizations)
return false;
}
// If crtfastmath.o exists add it to the arguments.
- std::string Path = GetFilePath("crtfastmath.o");
- if (Path == "crtfastmath.o") // Not found.
- return false;
+ Path = GetFilePath("crtfastmath.o");
+ return (Path != "crtfastmath.o"); // Not found.
+}
- CmdArgs.push_back(Args.MakeArgString(Path));
- return true;
+bool ToolChain::addFastMathRuntimeIfAvailable(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ std::string Path;
+ if (isFastMathRuntimeAvailable(Args, Path)) {
+ CmdArgs.push_back(Args.MakeArgString(Path));
+ return true;
+ }
+
+ return false;
}
SanitizerMask ToolChain::getSupportedSanitizers() const {
@@ -955,15 +1000,12 @@ SanitizerMask ToolChain::getSupportedSanitizers() const {
if (getTriple().getArch() == llvm::Triple::x86 ||
getTriple().getArch() == llvm::Triple::x86_64 ||
getTriple().getArch() == llvm::Triple::arm ||
- getTriple().getArch() == llvm::Triple::aarch64 ||
getTriple().getArch() == llvm::Triple::wasm32 ||
- getTriple().getArch() == llvm::Triple::wasm64)
+ getTriple().getArch() == llvm::Triple::wasm64 || getTriple().isAArch64())
Res |= SanitizerKind::CFIICall;
- if (getTriple().getArch() == llvm::Triple::x86_64 ||
- getTriple().getArch() == llvm::Triple::aarch64)
+ if (getTriple().getArch() == llvm::Triple::x86_64 || getTriple().isAArch64())
Res |= SanitizerKind::ShadowCallStack;
- if (getTriple().getArch() == llvm::Triple::aarch64 ||
- getTriple().getArch() == llvm::Triple::aarch64_be)
+ if (getTriple().isAArch64())
Res |= SanitizerKind::MemTag;
return Res;
}
@@ -971,6 +1013,9 @@ SanitizerMask ToolChain::getSupportedSanitizers() const {
void ToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {}
+void ToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {}
+
void ToolChain::AddIAMCUIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {}
@@ -1094,3 +1139,86 @@ llvm::opt::DerivedArgList *ToolChain::TranslateOpenMPTargetArgs(
delete DAL;
return nullptr;
}
+
+// TODO: Currently argument values separated by space e.g.
+// -Xclang -mframe-pointer=no cannot be passed by -Xarch_. This should be
+// fixed.
+void ToolChain::TranslateXarchArgs(
+ const llvm::opt::DerivedArgList &Args, llvm::opt::Arg *&A,
+ llvm::opt::DerivedArgList *DAL,
+ SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const {
+ const OptTable &Opts = getDriver().getOpts();
+ unsigned ValuePos = 1;
+ if (A->getOption().matches(options::OPT_Xarch_device) ||
+ A->getOption().matches(options::OPT_Xarch_host))
+ ValuePos = 0;
+
+ unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(ValuePos));
+ unsigned Prev = Index;
+ std::unique_ptr<llvm::opt::Arg> XarchArg(Opts.ParseOneArg(Args, Index));
+
+ // If the argument parsing failed or more than one argument was
+ // consumed, the -Xarch_ argument's parameter tried to consume
+ // extra arguments. Emit an error and ignore.
+ //
+ // We also want to disallow any options which would alter the
+ // driver behavior; that isn't going to work in our model. We
+ // use isDriverOption() as an approximation, although things
+ // like -O4 are going to slip through.
+ if (!XarchArg || Index > Prev + 1) {
+ getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args)
+ << A->getAsString(Args);
+ return;
+ } else if (XarchArg->getOption().hasFlag(options::DriverOption)) {
+ getDriver().Diag(diag::err_drv_invalid_Xarch_argument_isdriver)
+ << A->getAsString(Args);
+ return;
+ }
+ XarchArg->setBaseArg(A);
+ A = XarchArg.release();
+ if (!AllocatedArgs)
+ DAL->AddSynthesizedArg(A);
+ else
+ AllocatedArgs->push_back(A);
+}
+
+llvm::opt::DerivedArgList *ToolChain::TranslateXarchArgs(
+ const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+ Action::OffloadKind OFK,
+ SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const {
+ DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
+ bool Modified = false;
+
+ bool IsGPU = OFK == Action::OFK_Cuda || OFK == Action::OFK_HIP;
+ for (Arg *A : Args) {
+ bool NeedTrans = false;
+ bool Skip = false;
+ if (A->getOption().matches(options::OPT_Xarch_device)) {
+ NeedTrans = IsGPU;
+ Skip = !IsGPU;
+ } else if (A->getOption().matches(options::OPT_Xarch_host)) {
+ NeedTrans = !IsGPU;
+ Skip = IsGPU;
+ } else if (A->getOption().matches(options::OPT_Xarch__) && IsGPU) {
+ // Do not translate -Xarch_ options for non CUDA/HIP toolchain since
+ // they may need special translation.
+ // Skip this argument unless the architecture matches BoundArch
+ if (BoundArch.empty() || A->getValue(0) != BoundArch)
+ Skip = true;
+ else
+ NeedTrans = true;
+ }
+ if (NeedTrans || Skip)
+ Modified = true;
+ if (NeedTrans)
+ TranslateXarchArgs(Args, A, DAL, AllocatedArgs);
+ if (!Skip)
+ DAL->append(A);
+ }
+
+ if (Modified)
+ return DAL;
+
+ delete DAL;
+ return nullptr;
+}
diff --git a/clang/lib/Driver/ToolChains/AIX.cpp b/clang/lib/Driver/ToolChains/AIX.cpp
index 6fbff61f76565..ac5544eedb00b 100644
--- a/clang/lib/Driver/ToolChains/AIX.cpp
+++ b/clang/lib/Driver/ToolChains/AIX.cpp
@@ -13,12 +13,15 @@
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Support/Path.h"
using AIX = clang::driver::toolchains::AIX;
using namespace clang::driver;
using namespace clang::driver::tools;
+using namespace clang::driver::toolchains;
using namespace llvm::opt;
+using namespace llvm::sys;
void aix::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
@@ -73,7 +76,8 @@ void aix::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(II.getFilename());
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Exec, CmdArgs, Inputs));
}
void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -81,6 +85,7 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs, const ArgList &Args,
const char *LinkingOutput) const {
const AIX &ToolChain = static_cast<const AIX &>(getToolChain());
+ const Driver &D = ToolChain.getDriver();
ArgStringList CmdArgs;
const bool IsArch32Bit = ToolChain.getTriple().isArch32Bit();
@@ -129,6 +134,12 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.MakeArgString(ToolChain.GetFilePath(getCrt0Basename())));
}
+ // Collect all static constructor and destructor functions in CXX mode. This
+ // has to come before AddLinkerInputs as the implied option needs to precede
+ // any other '-bcdtors' settings or '-bnocdtors' that '-Wl' might forward.
+ if (D.CCCIsCXX())
+ CmdArgs.push_back("-bcdtors:all:0:s");
+
// Specify linker input file(s).
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
@@ -145,7 +156,8 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Exec, CmdArgs, Inputs));
}
/// AIX - AIX tool chain which can call as(1) and ld(1) directly.
@@ -154,6 +166,43 @@ AIX::AIX(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
}
+// Returns the effective header sysroot path to use.
+// This comes from either -isysroot or --sysroot.
+llvm::StringRef
+AIX::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 "/";
+}
+
+void AIX::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ // Return if -nostdinc is specified as a driver option.
+ if (DriverArgs.hasArg(options::OPT_nostdinc))
+ return;
+
+ 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());
+ }
+
+ // Return if -nostdlibinc is specified as a driver option.
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+
+ // Add <sysroot>/usr/include.
+ SmallString<128> UP(Sysroot);
+ path::append(UP, "/usr/include");
+ addSystemInclude(DriverArgs, CC1Args, UP.str());
+}
+
auto AIX::buildAssembler() const -> Tool * { return new aix::Assembler(*this); }
auto AIX::buildLinker() const -> Tool * { return new aix::Linker(*this); }
diff --git a/clang/lib/Driver/ToolChains/AIX.h b/clang/lib/Driver/ToolChains/AIX.h
index 69b948bc0ea82..942bb3cceb8a7 100644
--- a/clang/lib/Driver/ToolChains/AIX.h
+++ b/clang/lib/Driver/ToolChains/AIX.h
@@ -63,9 +63,16 @@ public:
bool isPIEDefault() const override { return false; }
bool isPICDefaultForced() const override { return true; }
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
+
+private:
+ llvm::StringRef GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const;
};
} // end namespace toolchains
diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp
index 71a2c68b4197b..bc6d1fcd4a008 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp
@@ -12,6 +12,8 @@
#include "clang/Driver/Compilation.h"
#include "clang/Driver/DriverDiagnostic.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;
@@ -19,6 +21,327 @@ using namespace clang::driver::toolchains;
using namespace clang;
using namespace llvm::opt;
+void RocmInstallationDetector::scanLibDevicePath(llvm::StringRef Path) {
+ assert(!Path.empty());
+
+ const StringRef Suffix(".bc");
+ const StringRef Suffix2(".amdgcn.bc");
+
+ std::error_code EC;
+ for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(Path, EC), LE;
+ !EC && LI != LE; LI = LI.increment(EC)) {
+ StringRef FilePath = LI->path();
+ StringRef FileName = llvm::sys::path::filename(FilePath);
+ if (!FileName.endswith(Suffix))
+ continue;
+
+ StringRef BaseName;
+ if (FileName.endswith(Suffix2))
+ BaseName = FileName.drop_back(Suffix2.size());
+ else if (FileName.endswith(Suffix))
+ BaseName = FileName.drop_back(Suffix.size());
+
+ if (BaseName == "ocml") {
+ OCML = FilePath;
+ } else if (BaseName == "ockl") {
+ OCKL = FilePath;
+ } else if (BaseName == "opencl") {
+ OpenCL = FilePath;
+ } else if (BaseName == "hip") {
+ HIP = FilePath;
+ } else if (BaseName == "oclc_finite_only_off") {
+ FiniteOnly.Off = FilePath;
+ } else if (BaseName == "oclc_finite_only_on") {
+ FiniteOnly.On = FilePath;
+ } else if (BaseName == "oclc_daz_opt_on") {
+ DenormalsAreZero.On = FilePath;
+ } else if (BaseName == "oclc_daz_opt_off") {
+ DenormalsAreZero.Off = FilePath;
+ } else if (BaseName == "oclc_correctly_rounded_sqrt_on") {
+ CorrectlyRoundedSqrt.On = FilePath;
+ } else if (BaseName == "oclc_correctly_rounded_sqrt_off") {
+ CorrectlyRoundedSqrt.Off = FilePath;
+ } else if (BaseName == "oclc_unsafe_math_on") {
+ UnsafeMath.On = FilePath;
+ } else if (BaseName == "oclc_unsafe_math_off") {
+ UnsafeMath.Off = FilePath;
+ } else if (BaseName == "oclc_wavefrontsize64_on") {
+ WavefrontSize64.On = FilePath;
+ } else if (BaseName == "oclc_wavefrontsize64_off") {
+ WavefrontSize64.Off = FilePath;
+ } else {
+ // Process all bitcode filenames that look like
+ // ocl_isa_version_XXX.amdgcn.bc
+ const StringRef DeviceLibPrefix = "oclc_isa_version_";
+ if (!BaseName.startswith(DeviceLibPrefix))
+ continue;
+
+ StringRef IsaVersionNumber =
+ BaseName.drop_front(DeviceLibPrefix.size());
+
+ llvm::Twine GfxName = Twine("gfx") + IsaVersionNumber;
+ SmallString<8> Tmp;
+ LibDeviceMap.insert(
+ std::make_pair(GfxName.toStringRef(Tmp), FilePath.str()));
+ }
+ }
+}
+
+void RocmInstallationDetector::ParseHIPVersionFile(llvm::StringRef V) {
+ SmallVector<StringRef, 4> VersionParts;
+ V.split(VersionParts, '\n');
+ unsigned Major;
+ unsigned Minor;
+ for (auto Part : VersionParts) {
+ auto Splits = Part.split('=');
+ if (Splits.first == "HIP_VERSION_MAJOR")
+ Splits.second.getAsInteger(0, Major);
+ else if (Splits.first == "HIP_VERSION_MINOR")
+ Splits.second.getAsInteger(0, Minor);
+ else if (Splits.first == "HIP_VERSION_PATCH")
+ VersionPatch = Splits.second.str();
+ }
+ VersionMajorMinor = llvm::VersionTuple(Major, Minor);
+ DetectedVersion =
+ (Twine(Major) + "." + Twine(Minor) + "." + VersionPatch).str();
+}
+
+// For candidate specified by --rocm-path we do not do strict check.
+SmallVector<RocmInstallationDetector::Candidate, 4>
+RocmInstallationDetector::getInstallationPathCandidates() {
+ SmallVector<Candidate, 4> Candidates;
+ if (!RocmPathArg.empty()) {
+ Candidates.emplace_back(RocmPathArg.str());
+ return Candidates;
+ }
+
+ // Try to find relative to the compiler binary.
+ const char *InstallDir = D.getInstalledDir();
+
+ // Check both a normal Unix prefix position of the clang binary, as well as
+ // the Windows-esque layout the ROCm packages use with the host architecture
+ // subdirectory of bin.
+
+ // Strip off directory (usually bin)
+ StringRef ParentDir = llvm::sys::path::parent_path(InstallDir);
+ StringRef ParentName = llvm::sys::path::filename(ParentDir);
+
+ // Some builds use bin/{host arch}, so go up again.
+ if (ParentName == "bin") {
+ ParentDir = llvm::sys::path::parent_path(ParentDir);
+ ParentName = llvm::sys::path::filename(ParentDir);
+ }
+
+ // Some versions of the rocm llvm package install to /opt/rocm/llvm/bin
+ if (ParentName == "llvm")
+ ParentDir = llvm::sys::path::parent_path(ParentDir);
+
+ Candidates.emplace_back(ParentDir.str(), /*StrictChecking=*/true);
+
+ // Device library may be installed in clang resource directory.
+ Candidates.emplace_back(D.ResourceDir, /*StrictChecking=*/true);
+
+ Candidates.emplace_back(D.SysRoot + "/opt/rocm", /*StrictChecking=*/true);
+ return Candidates;
+}
+
+RocmInstallationDetector::RocmInstallationDetector(
+ const Driver &D, const llvm::Triple &HostTriple,
+ const llvm::opt::ArgList &Args, bool DetectHIPRuntime, bool DetectDeviceLib)
+ : D(D) {
+ RocmPathArg = Args.getLastArgValue(clang::driver::options::OPT_rocm_path_EQ);
+ RocmDeviceLibPathArg =
+ Args.getAllArgValues(clang::driver::options::OPT_rocm_device_lib_path_EQ);
+ if (auto *A = Args.getLastArg(clang::driver::options::OPT_hip_version_EQ)) {
+ HIPVersionArg = A->getValue();
+ unsigned Major = 0;
+ unsigned Minor = 0;
+ SmallVector<StringRef, 3> Parts;
+ HIPVersionArg.split(Parts, '.');
+ if (Parts.size())
+ Parts[0].getAsInteger(0, Major);
+ if (Parts.size() > 1)
+ Parts[1].getAsInteger(0, Minor);
+ if (Parts.size() > 2)
+ VersionPatch = Parts[2].str();
+ if (VersionPatch.empty())
+ VersionPatch = "0";
+ if (Major == 0 || Minor == 0)
+ D.Diag(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << HIPVersionArg;
+
+ VersionMajorMinor = llvm::VersionTuple(Major, Minor);
+ DetectedVersion =
+ (Twine(Major) + "." + Twine(Minor) + "." + VersionPatch).str();
+ } else {
+ VersionPatch = DefaultVersionPatch;
+ VersionMajorMinor =
+ llvm::VersionTuple(DefaultVersionMajor, DefaultVersionMinor);
+ DetectedVersion = (Twine(DefaultVersionMajor) + "." +
+ Twine(DefaultVersionMinor) + "." + VersionPatch)
+ .str();
+ }
+
+ if (DetectHIPRuntime)
+ detectHIPRuntime();
+ if (DetectDeviceLib)
+ detectDeviceLibrary();
+}
+
+void RocmInstallationDetector::detectDeviceLibrary() {
+ assert(LibDevicePath.empty());
+
+ if (!RocmDeviceLibPathArg.empty())
+ LibDevicePath = RocmDeviceLibPathArg[RocmDeviceLibPathArg.size() - 1];
+ else if (const char *LibPathEnv = ::getenv("HIP_DEVICE_LIB_PATH"))
+ LibDevicePath = LibPathEnv;
+
+ auto &FS = D.getVFS();
+ if (!LibDevicePath.empty()) {
+ // Maintain compatability with HIP flag/envvar pointing directly at the
+ // bitcode library directory. This points directly at the library path instead
+ // of the rocm root installation.
+ if (!FS.exists(LibDevicePath))
+ return;
+
+ scanLibDevicePath(LibDevicePath);
+ HasDeviceLibrary = allGenericLibsValid() && !LibDeviceMap.empty();
+ 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 Candidates = getInstallationPathCandidates();
+ for (const auto &Candidate : Candidates) {
+ 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);
+
+ if (!NoBuiltinLibs) {
+ // Check that the required non-target libraries are all available.
+ if (!allGenericLibsValid())
+ return false;
+
+ // 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;
+ };
+
+ // The possible structures are:
+ // - ${ROCM_ROOT}/amdgcn/bitcode/*
+ // - ${ROCM_ROOT}/lib/*
+ // - ${ROCM_ROOT}/lib/bitcode/*
+ // so try to detect these layouts.
+ static llvm::SmallVector<const char *, 2> SubDirsList[] = {
+ {"amdgcn", "bitcode"},
+ {"lib"},
+ {"lib", "bitcode"},
+ };
+
+ // 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;
+ };
+
+ for (auto SubDirs : SubDirsList) {
+ LibDevicePath = MakePath(SubDirs);
+ HasDeviceLibrary = CheckDeviceLib(LibDevicePath);
+ if (HasDeviceLibrary)
+ return;
+ }
+ }
+}
+
+void RocmInstallationDetector::detectHIPRuntime() {
+ auto Candidates = getInstallationPathCandidates();
+ auto &FS = D.getVFS();
+
+ for (const auto &Candidate : Candidates) {
+ InstallPath = Candidate.Path;
+ if (InstallPath.empty() || !FS.exists(InstallPath))
+ continue;
+
+ BinPath = InstallPath;
+ llvm::sys::path::append(BinPath, "bin");
+ IncludePath = InstallPath;
+ 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)
+ ParseHIPVersionFile((*VersionFile)->getBuffer());
+
+ HasHIPRuntime = true;
+ return;
+ }
+ HasHIPRuntime = false;
+}
+
+void RocmInstallationDetector::print(raw_ostream &OS) const {
+ if (hasHIPRuntime())
+ OS << "Found HIP installation: " << InstallPath << ", version "
+ << DetectedVersion << '\n';
+}
+
+void RocmInstallationDetector::AddHIPIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ bool UsesRuntimeWrapper = VersionMajorMinor > llvm::VersionTuple(3, 5);
+
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+ // HIP header includes standard library wrapper headers under clang
+ // cuda_wrappers directory. Since these wrapper headers include_next
+ // standard C++ headers, whereas libc++ headers include_next other clang
+ // headers. The include paths have to follow this order:
+ // - wrapper include path
+ // - standard C++ include path
+ // - other clang include path
+ // Since standard C++ and other clang include paths are added in other
+ // places after this function, here we only need to make sure wrapper
+ // include path is added.
+ //
+ // ROCm 3.5 does not fully support the wrapper headers. Therefore it needs
+ // a workaround.
+ SmallString<128> P(D.ResourceDir);
+ if (UsesRuntimeWrapper)
+ llvm::sys::path::append(P, "include", "cuda_wrappers");
+ CC1Args.push_back("-internal-isystem");
+ CC1Args.push_back(DriverArgs.MakeArgString(P));
+ }
+
+ if (DriverArgs.hasArg(options::OPT_nogpuinc))
+ return;
+
+ if (!hasHIPRuntime()) {
+ D.Diag(diag::err_drv_no_hip_runtime);
+ return;
+ }
+
+ CC1Args.push_back("-internal-isystem");
+ CC1Args.push_back(DriverArgs.MakeArgString(getIncludePath()));
+ if (UsesRuntimeWrapper)
+ CC1Args.append({"-include", "__clang_hip_runtime_wrapper.h"});
+}
+
void amdgpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -31,8 +354,9 @@ void amdgpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-shared");
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
- CmdArgs, Inputs));
+ C.addCommand(
+ std::make_unique<Command>(JA, *this, ResponseFileSupport::AtFileCurCP(),
+ Args.MakeArgString(Linker), CmdArgs, Inputs));
}
void amdgpu::getAMDGPUTargetFeatures(const Driver &D,
@@ -102,6 +426,73 @@ AMDGPUToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
return DAL;
}
+bool AMDGPUToolChain::getDefaultDenormsAreZeroForTarget(
+ llvm::AMDGPU::GPUKind Kind) {
+
+ // Assume nothing without a specific target.
+ if (Kind == llvm::AMDGPU::GK_NONE)
+ return false;
+
+ const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
+
+ // Default to enabling f32 denormals by default on subtargets where fma is
+ // fast with denormals
+ const bool BothDenormAndFMAFast =
+ (ArchAttr & llvm::AMDGPU::FEATURE_FAST_FMA_F32) &&
+ (ArchAttr & llvm::AMDGPU::FEATURE_FAST_DENORMAL_F32);
+ return !BothDenormAndFMAFast;
+}
+
+llvm::DenormalMode AMDGPUToolChain::getDefaultDenormalModeForType(
+ const llvm::opt::ArgList &DriverArgs, const JobAction &JA,
+ const llvm::fltSemantics *FPType) const {
+ // Denormals should always be enabled for f16 and f64.
+ if (!FPType || FPType != &llvm::APFloat::IEEEsingle())
+ return llvm::DenormalMode::getIEEE();
+
+ if (JA.getOffloadingDeviceKind() == Action::OFK_HIP ||
+ JA.getOffloadingDeviceKind() == Action::OFK_Cuda) {
+ auto Kind = llvm::AMDGPU::parseArchAMDGCN(JA.getOffloadingArch());
+ if (FPType && FPType == &llvm::APFloat::IEEEsingle() &&
+ DriverArgs.hasFlag(options::OPT_fcuda_flush_denormals_to_zero,
+ options::OPT_fno_cuda_flush_denormals_to_zero,
+ getDefaultDenormsAreZeroForTarget(Kind)))
+ return llvm::DenormalMode::getPreserveSign();
+
+ return llvm::DenormalMode::getIEEE();
+ }
+
+ const StringRef GpuArch = DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
+ auto Kind = llvm::AMDGPU::parseArchAMDGCN(GpuArch);
+
+ // TODO: There are way too many flags that change this. Do we need to check
+ // them all?
+ bool DAZ = DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) ||
+ getDefaultDenormsAreZeroForTarget(Kind);
+
+ // Outputs are flushed to zero (FTZ), preserving sign. Denormal inputs are
+ // also implicit treated as zero (DAZ).
+ return DAZ ? llvm::DenormalMode::getPreserveSign() :
+ llvm::DenormalMode::getIEEE();
+}
+
+bool AMDGPUToolChain::isWave64(const llvm::opt::ArgList &DriverArgs,
+ llvm::AMDGPU::GPUKind Kind) {
+ const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
+ static bool HasWave32 = (ArchAttr & llvm::AMDGPU::FEATURE_WAVE32);
+
+ return !HasWave32 || DriverArgs.hasFlag(
+ options::OPT_mwavefrontsize64, options::OPT_mno_wavefrontsize64, false);
+}
+
+
+/// ROCM Toolchain
+ROCMToolChain::ROCMToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : AMDGPUToolChain(D, Triple, Args) {
+ RocmInstallation.detectDeviceLibrary();
+}
+
void AMDGPUToolChain::addClangTargetOptions(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
@@ -115,3 +506,91 @@ void AMDGPUToolChain::addClangTargetOptions(
CC1Args.push_back("-fapply-global-visibility-to-externs");
}
}
+
+void ROCMToolChain::addClangTargetOptions(
+ const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadingKind) const {
+ AMDGPUToolChain::addClangTargetOptions(DriverArgs, CC1Args,
+ DeviceOffloadingKind);
+
+ // For the OpenCL case where there is no offload target, accept -nostdlib to
+ // disable bitcode linking.
+ if (DeviceOffloadingKind == Action::OFK_None &&
+ DriverArgs.hasArg(options::OPT_nostdlib))
+ return;
+
+ 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 = DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
+ auto Kind = llvm::AMDGPU::parseArchAMDGCN(GpuArch);
+ const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind);
+ std::string LibDeviceFile = RocmInstallation.getLibDeviceFile(CanonArch);
+ if (LibDeviceFile.empty()) {
+ getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 1 << GpuArch;
+ return;
+ }
+
+ bool Wave64 = isWave64(DriverArgs, Kind);
+
+ // TODO: There are way too many flags that change this. Do we need to check
+ // them all?
+ bool DAZ = DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) ||
+ getDefaultDenormsAreZeroForTarget(Kind);
+ bool FiniteOnly = DriverArgs.hasArg(options::OPT_cl_finite_math_only);
+
+ bool UnsafeMathOpt =
+ DriverArgs.hasArg(options::OPT_cl_unsafe_math_optimizations);
+ bool FastRelaxedMath = DriverArgs.hasArg(options::OPT_cl_fast_relaxed_math);
+ bool CorrectSqrt =
+ DriverArgs.hasArg(options::OPT_cl_fp32_correctly_rounded_divide_sqrt);
+
+ // Add the OpenCL specific bitcode library.
+ CC1Args.push_back("-mlink-builtin-bitcode");
+ CC1Args.push_back(DriverArgs.MakeArgString(RocmInstallation.getOpenCLPath()));
+
+ // Add the generic set of libraries.
+ RocmInstallation.addCommonBitcodeLibCC1Args(
+ DriverArgs, CC1Args, LibDeviceFile, Wave64, DAZ, FiniteOnly,
+ UnsafeMathOpt, FastRelaxedMath, CorrectSqrt);
+}
+
+void RocmInstallationDetector::addCommonBitcodeLibCC1Args(
+ const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
+ StringRef LibDeviceFile, bool Wave64, bool DAZ, bool FiniteOnly,
+ bool UnsafeMathOpt, bool FastRelaxedMath, bool CorrectSqrt) const {
+ static const char LinkBitcodeFlag[] = "-mlink-builtin-bitcode";
+
+ CC1Args.push_back(LinkBitcodeFlag);
+ CC1Args.push_back(DriverArgs.MakeArgString(getOCMLPath()));
+
+ CC1Args.push_back(LinkBitcodeFlag);
+ CC1Args.push_back(DriverArgs.MakeArgString(getOCKLPath()));
+
+ CC1Args.push_back(LinkBitcodeFlag);
+ CC1Args.push_back(DriverArgs.MakeArgString(getDenormalsAreZeroPath(DAZ)));
+
+ CC1Args.push_back(LinkBitcodeFlag);
+ CC1Args.push_back(DriverArgs.MakeArgString(
+ getUnsafeMathPath(UnsafeMathOpt || FastRelaxedMath)));
+
+ CC1Args.push_back(LinkBitcodeFlag);
+ CC1Args.push_back(DriverArgs.MakeArgString(
+ getFiniteOnlyPath(FiniteOnly || FastRelaxedMath)));
+
+ CC1Args.push_back(LinkBitcodeFlag);
+ CC1Args.push_back(
+ DriverArgs.MakeArgString(getCorrectlyRoundedSqrtPath(CorrectSqrt)));
+
+ CC1Args.push_back(LinkBitcodeFlag);
+ CC1Args.push_back(DriverArgs.MakeArgString(getWavefrontSize64Path(Wave64)));
+
+ CC1Args.push_back(LinkBitcodeFlag);
+ CC1Args.push_back(DriverArgs.MakeArgString(LibDeviceFile));
+}
diff --git a/clang/lib/Driver/ToolChains/AMDGPU.h b/clang/lib/Driver/ToolChains/AMDGPU.h
index f4c78bea5cc97..5d44faf28b053 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.h
+++ b/clang/lib/Driver/ToolChains/AMDGPU.h
@@ -10,19 +10,24 @@
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_AMDGPU_H
#include "Gnu.h"
+#include "ROCm.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/TargetParser.h"
+
#include <map>
namespace clang {
namespace driver {
+
namespace tools {
namespace amdgpu {
-class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
- Linker(const ToolChain &TC) : GnuTool("amdgpu::Linker", "ld.lld", TC) {}
+ Linker(const ToolChain &TC) : Tool("amdgpu::Linker", "ld.lld", TC) {}
bool isLinkJob() const override { return true; }
bool hasIntegratedCPP() const override { return false; }
void ConstructJob(Compilation &C, const JobAction &JA,
@@ -40,11 +45,9 @@ void getAMDGPUTargetFeatures(const Driver &D, const llvm::opt::ArgList &Args,
namespace toolchains {
class LLVM_LIBRARY_VISIBILITY AMDGPUToolChain : public Generic_ELF {
-
-private:
+protected:
const std::map<options::ID, const StringRef> OptionsDefault;
-protected:
Tool *buildLinker() const override;
const StringRef getOptionDefault(options::ID OptID) const {
auto opt = OptionsDefault.find(OptID);
@@ -66,6 +69,34 @@ public:
void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadKind) const override;
+
+ /// Return whether denormals should be flushed, and treated as 0 by default
+ /// for the subtarget.
+ static bool getDefaultDenormsAreZeroForTarget(llvm::AMDGPU::GPUKind GPUKind);
+
+ llvm::DenormalMode getDefaultDenormalModeForType(
+ const llvm::opt::ArgList &DriverArgs, const JobAction &JA,
+ const llvm::fltSemantics *FPType = nullptr) const override;
+
+ static bool isWave64(const llvm::opt::ArgList &DriverArgs,
+ llvm::AMDGPU::GPUKind Kind);
+ /// Needed for using lto.
+ bool HasNativeLLVMSupport() const override {
+ return true;
+ }
+
+ /// Needed for translating LTO options.
+ const char *getDefaultLinker() const override { return "ld.lld"; }
+};
+
+class LLVM_LIBRARY_VISIBILITY ROCMToolChain : public AMDGPUToolChain {
+public:
+ ROCMToolChain(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 DeviceOffloadKind) const override;
};
} // end namespace toolchains
diff --git a/clang/lib/Driver/ToolChains/AVR.cpp b/clang/lib/Driver/ToolChains/AVR.cpp
index e8a3a7b38c31f..092bade53c635 100644
--- a/clang/lib/Driver/ToolChains/AVR.cpp
+++ b/clang/lib/Driver/ToolChains/AVR.cpp
@@ -74,13 +74,11 @@ AVRToolChain::AVRToolChain(const Driver &D, const llvm::Triple &Triple,
// 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 GCCRoot = std::string(GCCInstallation.getInstallPath());
std::string LibcRoot = AVRLibcRoot.getValue();
getFilePaths().push_back(LibcRoot + std::string("/lib/") +
std::string(*FamilyName));
- getFilePaths().push_back(LibcRoot + std::string("/lib/") +
- std::string(*FamilyName));
getFilePaths().push_back(GCCRoot + std::string("/") +
std::string(*FamilyName));
@@ -144,8 +142,9 @@ void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(std::string("-m") + *FamilyName));
}
- C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
- CmdArgs, Inputs));
+ C.addCommand(
+ std::make_unique<Command>(JA, *this, ResponseFileSupport::AtFileCurCP(),
+ Args.MakeArgString(Linker), CmdArgs, Inputs));
}
llvm::Optional<std::string> AVRToolChain::findAVRLibcInstallation() const {
diff --git a/clang/lib/Driver/ToolChains/AVR.h b/clang/lib/Driver/ToolChains/AVR.h
index d244fc4f90e90..a3198b2495803 100644
--- a/clang/lib/Driver/ToolChains/AVR.h
+++ b/clang/lib/Driver/ToolChains/AVR.h
@@ -40,10 +40,10 @@ private:
namespace tools {
namespace AVR {
-class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
Linker(const llvm::Triple &Triple, const ToolChain &TC, bool LinkStdlib)
- : GnuTool("AVR::Linker", "avr-ld", TC), Triple(Triple),
+ : Tool("AVR::Linker", "avr-ld", TC), Triple(Triple),
LinkStdlib(LinkStdlib) {}
bool hasIntegratedCPP() const override { return false; }
diff --git a/clang/lib/Driver/ToolChains/Ananas.cpp b/clang/lib/Driver/ToolChains/Ananas.cpp
index 2f11c9739a0eb..a4141a57acccb 100644
--- a/clang/lib/Driver/ToolChains/Ananas.cpp
+++ b/clang/lib/Driver/ToolChains/Ananas.cpp
@@ -39,7 +39,8 @@ void ananas::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(II.getFilename());
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
}
void ananas::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -103,7 +104,7 @@ void ananas::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (D.isUsingLTO()) {
assert(!Inputs.empty() && "Must have at least one input.");
- AddGoldPlugin(ToolChain, Args, CmdArgs, Output, Inputs[0],
+ addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs[0],
D.getLTOMode() == LTOK_Thin);
}
@@ -123,7 +124,8 @@ void ananas::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
}
// Ananas - Ananas tool chain which can call as(1) and ld(1) directly.
diff --git a/clang/lib/Driver/ToolChains/Ananas.h b/clang/lib/Driver/ToolChains/Ananas.h
index 5e45b47fc1083..72ad3edcf0567 100644
--- a/clang/lib/Driver/ToolChains/Ananas.h
+++ b/clang/lib/Driver/ToolChains/Ananas.h
@@ -19,10 +19,9 @@ namespace tools {
/// ananas -- Directly call GNU Binutils assembler and linker
namespace ananas {
-class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
public:
- Assembler(const ToolChain &TC)
- : GnuTool("ananas::Assembler", "assembler", TC) {}
+ Assembler(const ToolChain &TC) : Tool("ananas::Assembler", "assembler", TC) {}
bool hasIntegratedCPP() const override { return false; }
@@ -32,9 +31,9 @@ public:
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
- Linker(const ToolChain &TC) : GnuTool("ananas::Linker", "linker", TC) {}
+ Linker(const ToolChain &TC) : Tool("ananas::Linker", "linker", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
index 9c27504dccf5b..487c50dfc4663 100644
--- a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
@@ -39,7 +39,7 @@ std::string aarch64::getAArch64TargetCPU(const ArgList &Args,
// Handle CPU name is 'native'.
if (CPU == "native")
- return llvm::sys::getHostCPUName();
+ return std::string(llvm::sys::getHostCPUName());
else if (CPU.size())
return CPU;
@@ -54,7 +54,8 @@ 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) {
+ std::vector<StringRef> &Features,
+ llvm::AArch64::ArchKind ArchKind) {
SmallVector<StringRef, 8> Split;
text.split(Split, StringRef("+"), -1, false);
@@ -66,6 +67,11 @@ static bool DecodeAArch64Features(const Driver &D, StringRef text,
D.Diag(clang::diag::err_drv_no_neon_modifier);
else
return false;
+
+ // +sve implies +f32mm if the base architecture is v8.6A
+ // it isn't the case in general that sve implies both f64mm and f32mm
+ if ((ArchKind == llvm::AArch64::ArchKind::ARMV8_6A) && Feature == "sve")
+ Features.push_back("+f32mm");
}
return true;
}
@@ -76,6 +82,7 @@ static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
std::vector<StringRef> &Features) {
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();
@@ -83,7 +90,7 @@ static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
if (CPU == "generic") {
Features.push_back("+neon");
} else {
- llvm::AArch64::ArchKind ArchKind = llvm::AArch64::parseCPUArch(CPU);
+ ArchKind = llvm::AArch64::parseCPUArch(CPU);
if (!llvm::AArch64::getArchFeatures(ArchKind, Features))
return false;
@@ -92,10 +99,11 @@ static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
return false;
}
- if (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features))
- return false;
+ if (Split.second.size() &&
+ !DecodeAArch64Features(D, Split.second, Features, ArchKind))
+ return false;
- return true;
+ return true;
}
static bool
@@ -108,7 +116,8 @@ getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
llvm::AArch64::ArchKind ArchKind = llvm::AArch64::parseArch(Split.first);
if (ArchKind == llvm::AArch64::ArchKind::INVALID ||
!llvm::AArch64::getArchFeatures(ArchKind, Features) ||
- (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features)))
+ (Split.second.size() &&
+ !DecodeAArch64Features(D, Split.second, Features, ArchKind)))
return false;
return true;
@@ -139,8 +148,9 @@ getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,
// Handle CPU name is 'native'.
if (MtuneLowerCase == "native")
- MtuneLowerCase = llvm::sys::getHostCPUName();
- if (MtuneLowerCase == "cyclone" || MtuneLowerCase.find("apple") == 0) {
+ MtuneLowerCase = std::string(llvm::sys::getHostCPUName());
+ if (MtuneLowerCase == "cyclone" ||
+ StringRef(MtuneLowerCase).startswith("apple")) {
Features.push_back("+zcm");
Features.push_back("+zcz");
}
@@ -208,6 +218,39 @@ void aarch64::getAArch64TargetFeatures(const Driver &D,
D.Diag(diag::err_drv_invalid_mtp) << A->getAsString(Args);
}
+ // Enable/disable straight line speculation hardening.
+ if (Arg *A = Args.getLastArg(options::OPT_mharden_sls_EQ)) {
+ StringRef Scope = A->getValue();
+ bool EnableRetBr = false;
+ bool EnableBlr = false;
+ if (Scope != "none" && Scope != "all") {
+ SmallVector<StringRef, 4> Opts;
+ Scope.split(Opts, ",");
+ for (auto Opt : Opts) {
+ Opt = Opt.trim();
+ if (Opt == "retbr") {
+ EnableRetBr = true;
+ continue;
+ }
+ if (Opt == "blr") {
+ EnableBlr = true;
+ continue;
+ }
+ D.Diag(diag::err_invalid_sls_hardening)
+ << Scope << A->getAsString(Args);
+ break;
+ }
+ } else if (Scope == "all") {
+ EnableRetBr = true;
+ EnableBlr = true;
+ }
+
+ if (EnableRetBr)
+ Features.push_back("+harden-sls-retbr");
+ if (EnableBlr)
+ Features.push_back("+harden-sls-blr");
+ }
+
// En/disable crc
if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {
if (A->getOption().matches(options::OPT_mcrc))
@@ -322,6 +365,10 @@ fp16_fml_fallthrough:
}
}
+ auto V8_6Pos = llvm::find(Features, "+v8.6a");
+ if (V8_6Pos != std::end(Features))
+ V8_6Pos = Features.insert(std::next(V8_6Pos), {"+i8mm", "+bf16"});
+
if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
options::OPT_munaligned_access))
if (A->getOption().matches(options::OPT_mno_unaligned_access))
@@ -399,6 +446,9 @@ fp16_fml_fallthrough:
if (Args.hasArg(options::OPT_ffixed_x28))
Features.push_back("+reserve-x28");
+ if (Args.hasArg(options::OPT_ffixed_x30))
+ Features.push_back("+reserve-x30");
+
if (Args.hasArg(options::OPT_fcall_saved_x8))
Features.push_back("+call-saved-x8");
diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
index a1923e731489e..afe896b4a65bf 100644
--- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -57,7 +57,7 @@ void arm::getARMArchCPUFromArgs(const ArgList &Args, llvm::StringRef &Arch,
static void getARMHWDivFeatures(const Driver &D, const Arg *A,
const ArgList &Args, StringRef HWDiv,
std::vector<StringRef> &Features) {
- unsigned HWDivID = llvm::ARM::parseHWDiv(HWDiv);
+ uint64_t HWDivID = llvm::ARM::parseHWDiv(HWDiv);
if (!llvm::ARM::getHWDivFeatures(HWDivID, Features))
D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
}
@@ -91,7 +91,7 @@ static void DecodeARMFeaturesFromCPU(const Driver &D, StringRef CPU,
CPU = CPU.split("+").first;
if (CPU != "generic") {
llvm::ARM::ArchKind ArchKind = llvm::ARM::parseCPUArch(CPU);
- unsigned Extension = llvm::ARM::getDefaultExtensions(CPU, ArchKind);
+ uint64_t Extension = llvm::ARM::getDefaultExtensions(CPU, ArchKind);
llvm::ARM::getExtensionFeatures(Extension, Features);
}
}
@@ -137,9 +137,8 @@ bool arm::useAAPCSForMachO(const llvm::Triple &T) {
}
// Select mode for reading thread pointer (-mtp=soft/cp15).
-arm::ReadTPMode arm::getReadTPMode(const ToolChain &TC, const ArgList &Args) {
+arm::ReadTPMode arm::getReadTPMode(const Driver &D, const ArgList &Args) {
if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) {
- const Driver &D = TC.getDriver();
arm::ReadTPMode ThreadPointer =
llvm::StringSwitch<arm::ReadTPMode>(A->getValue())
.Case("cp15", ReadTPMode::Cp15)
@@ -156,11 +155,14 @@ arm::ReadTPMode arm::getReadTPMode(const ToolChain &TC, const ArgList &Args) {
return ReadTPMode::Soft;
}
+arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) {
+ return arm::getARMFloatABI(TC.getDriver(), TC.getEffectiveTriple(), Args);
+}
+
// Select the float ABI as determined by -msoft-float, -mhard-float, and
// -mfloat-abi=.
-arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) {
- const Driver &D = TC.getDriver();
- const llvm::Triple &Triple = TC.getEffectiveTriple();
+arm::FloatABI arm::getARMFloatABI(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args) {
auto SubArch = getARMSubArchVersionNumber(Triple);
arm::FloatABI ABI = FloatABI::Invalid;
if (Arg *A =
@@ -276,18 +278,20 @@ arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) {
return ABI;
}
-void arm::getARMTargetFeatures(const ToolChain &TC,
- const llvm::Triple &Triple,
- const ArgList &Args,
- ArgStringList &CmdArgs,
- std::vector<StringRef> &Features,
- bool ForAS) {
- const Driver &D = TC.getDriver();
+static bool hasIntegerMVE(const std::vector<StringRef> &F) {
+ auto MVE = llvm::find(llvm::reverse(F), "+mve");
+ auto NoMVE = llvm::find(llvm::reverse(F), "-mve");
+ return MVE != F.rend() &&
+ (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) {
bool KernelOrKext =
Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
- arm::FloatABI ABI = arm::getARMFloatABI(TC, Args);
- arm::ReadTPMode ThreadPointer = arm::getReadTPMode(TC, Args);
+ arm::FloatABI ABI = arm::getARMFloatABI(D, Triple, Args);
+ arm::ReadTPMode ThreadPointer = arm::getReadTPMode(D, Args);
const Arg *WaCPU = nullptr, *WaFPU = nullptr;
const Arg *WaHDiv = nullptr, *WaArch = nullptr;
@@ -459,18 +463,13 @@ fp16_fml_fallthrough:
// Disable all features relating to hardware FP, not already disabled by the
// above call.
- Features.insert(Features.end(), {"-neon", "-crypto", "-dotprod", "-fp16fml",
- "-mve", "-mve.fp", "-fpregs"});
+ Features.insert(Features.end(),
+ {"-dotprod", "-fp16fml", "-mve", "-mve.fp", "-fpregs"});
} else if (FPUID == llvm::ARM::FK_NONE) {
// -mfpu=none is *very* similar to -mfloat-abi=soft, only that it should not
// disable MVE-I.
- Features.insert(Features.end(),
- {"-neon", "-crypto", "-dotprod", "-fp16fml", "-mve.fp"});
- // Even though we remove MVE-FP, we still need to check if it was originally
- // present among the requested extensions, because it implies MVE-I, which
- // should not be disabled by -mfpu-none.
- if (!llvm::is_contained(Features, "+mve") &&
- !llvm::is_contained(Features, "+mve.fp"))
+ Features.insert(Features.end(), {"-dotprod", "-fp16fml", "-mve.fp"});
+ if (!hasIntegerMVE(Features))
Features.emplace_back("-fpregs");
}
@@ -612,14 +611,14 @@ fp16_fml_fallthrough:
const std::string arm::getARMArch(StringRef Arch, const llvm::Triple &Triple) {
std::string MArch;
if (!Arch.empty())
- MArch = Arch;
+ MArch = std::string(Arch);
else
- MArch = Triple.getArchName();
+ MArch = std::string(Triple.getArchName());
MArch = StringRef(MArch).split("+").first.lower();
// Handle -march=native.
if (MArch == "native") {
- std::string CPU = llvm::sys::getHostCPUName();
+ std::string CPU = std::string(llvm::sys::getHostCPUName());
if (CPU != "generic") {
// Translate the native cpu into the architecture suffix for that CPU.
StringRef Suffix = arm::getLLVMArchSuffixForARM(CPU, MArch, Triple);
@@ -657,12 +656,12 @@ std::string arm::getARMTargetCPU(StringRef CPU, StringRef Arch,
std::string MCPU = StringRef(CPU).split("+").first.lower();
// Handle -mcpu=native.
if (MCPU == "native")
- return llvm::sys::getHostCPUName();
+ return std::string(llvm::sys::getHostCPUName());
else
return MCPU;
}
- return getARMCPUForMArch(Arch, Triple);
+ return std::string(getARMCPUForMArch(Arch, Triple));
}
/// getLLVMArchSuffixForARM - Get the LLVM ArchKind value to use for a
diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.h b/clang/lib/Driver/ToolChains/Arch/ARM.h
index 5640f8371262a..0ba1a59852aa0 100644
--- a/clang/lib/Driver/ToolChains/Arch/ARM.h
+++ b/clang/lib/Driver/ToolChains/Arch/ARM.h
@@ -48,13 +48,15 @@ enum class FloatABI {
};
FloatABI getARMFloatABI(const ToolChain &TC, const llvm::opt::ArgList &Args);
-ReadTPMode getReadTPMode(const ToolChain &TC, const llvm::opt::ArgList &Args);
+FloatABI getARMFloatABI(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+ReadTPMode getReadTPMode(const Driver &D, const llvm::opt::ArgList &Args);
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 ToolChain &TC, const llvm::Triple &Triple,
+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);
diff --git a/clang/lib/Driver/ToolChains/Arch/PPC.cpp b/clang/lib/Driver/ToolChains/Arch/PPC.cpp
index f1baadaebf41b..144e276a6bd87 100644
--- a/clang/lib/Driver/ToolChains/Arch/PPC.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/PPC.cpp
@@ -26,7 +26,7 @@ std::string ppc::getPPCTargetCPU(const ArgList &Args) {
StringRef CPUName = A->getValue();
if (CPUName == "native") {
- std::string CPU = llvm::sys::getHostCPUName();
+ std::string CPU = std::string(llvm::sys::getHostCPUName());
if (!CPU.empty() && CPU != "generic")
return CPU;
else
@@ -70,6 +70,7 @@ std::string ppc::getPPCTargetCPU(const ArgList &Args) {
.Case("power7", "pwr7")
.Case("power8", "pwr8")
.Case("power9", "pwr9")
+ .Case("power10", "pwr10")
.Case("future", "future")
.Case("pwr3", "pwr3")
.Case("pwr4", "pwr4")
@@ -80,6 +81,7 @@ std::string ppc::getPPCTargetCPU(const ArgList &Args) {
.Case("pwr7", "pwr7")
.Case("pwr8", "pwr8")
.Case("pwr9", "pwr9")
+ .Case("pwr10", "pwr10")
.Case("powerpc", "ppc")
.Case("powerpc64", "ppc64")
.Case("powerpc64le", "ppc64le")
@@ -91,14 +93,16 @@ std::string ppc::getPPCTargetCPU(const ArgList &Args) {
const char *ppc::getPPCAsmModeForCPU(StringRef Name) {
return llvm::StringSwitch<const char *>(Name)
- .Case("pwr7", "-mpower7")
- .Case("power7", "-mpower7")
- .Case("pwr8", "-mpower8")
- .Case("power8", "-mpower8")
- .Case("ppc64le", "-mpower8")
- .Case("pwr9", "-mpower9")
- .Case("power9", "-mpower9")
- .Default("-many");
+ .Case("pwr7", "-mpower7")
+ .Case("power7", "-mpower7")
+ .Case("pwr8", "-mpower8")
+ .Case("power8", "-mpower8")
+ .Case("ppc64le", "-mpower8")
+ .Case("pwr9", "-mpower9")
+ .Case("power9", "-mpower9")
+ .Case("pwr10", "-mpower10")
+ .Case("power10", "-mpower10")
+ .Default("-many");
}
void ppc::getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,
diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
index 8c343b8693f32..80d12e5aa8daa 100644
--- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -22,6 +22,14 @@ 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";
@@ -29,6 +37,8 @@ static StringRef getExtensionTypeDesc(StringRef Ext) {
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();
}
@@ -39,10 +49,29 @@ static StringRef getExtensionType(StringRef Ext) {
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 == "zbb" || Ext == "zbc" || Ext == "zbe" ||
+ Ext == "zbf" || Ext == "zbm" || Ext == "zbp" || Ext == "zbr" ||
+ Ext == "zbs" || Ext == "zbt" || Ext == "zbproposedc")
+ return RISCVExtensionVersion{"0", "92"};
+ if (Ext == "v")
+ return RISCVExtensionVersion{"0", "8"};
+ 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;
}
@@ -52,17 +81,15 @@ static bool isSupportedExtension(StringRef Ext) {
// 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, StringRef MArch,
- StringRef Ext, StringRef In,
+static bool getExtensionVersion(const Driver &D, const ArgList &Args,
+ StringRef MArch, StringRef Ext, StringRef In,
std::string &Major, std::string &Minor) {
- Major = In.take_while(isDigit);
+ Major = std::string(In.take_while(isDigit));
In = In.substr(Major.size());
- if (Major.empty())
- return true;
- if (In.consume_front("p")) {
- Minor = 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()) {
@@ -74,7 +101,53 @@ static bool getExtensionVersion(const Driver &D, StringRef MArch,
}
}
- // TODO: Handle extensions with version number.
+ // 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;
@@ -89,7 +162,7 @@ static bool getExtensionVersion(const Driver &D, StringRef MArch,
// Parse the ISA string containing non-standard user-level
// extensions, standard supervisor-level extensions and
// non-standard supervisor-level extensions.
-// These extensions start with 'x', 's', 'sx' prefixes, follow a
+// 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.
@@ -105,7 +178,7 @@ static void getExtensionFeatures(const Driver &D,
SmallVector<StringRef, 8> Split;
Exts.split(Split, StringRef("_"));
- SmallVector<StringRef, 3> Prefix{"x", "s", "sx"};
+ SmallVector<StringRef, 4> Prefix{"z", "x", "s", "sx"};
auto I = Prefix.begin();
auto E = Prefix.end();
@@ -119,8 +192,10 @@ static void getExtensionFeatures(const Driver &D,
}
StringRef Type = getExtensionType(Ext);
- StringRef Name(Ext.substr(Type.size()));
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)
@@ -133,7 +208,7 @@ static void getExtensionFeatures(const Driver &D,
++I;
if (I == E) {
- std::string Error = Desc;
+ 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;
@@ -143,35 +218,30 @@ static void getExtensionFeatures(const Driver &D,
// The order is OK, do not advance I to the next prefix
// to allow repeated extension type, e.g.: rv32ixabc_xdef.
- if (Name.empty()) {
- std::string Error = Desc;
+ 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 << Ext;
+ << MArch << Error << Type;
return;
}
std::string Major, Minor;
- auto Pos = Name.find_if(isDigit);
- if (Pos != StringRef::npos) {
- auto Next = Name.substr(Pos);
- Name = Name.substr(0, Pos);
- if (!getExtensionVersion(D, MArch, Ext, Next, Major, Minor))
- return;
- }
+ if (!getExtensionVersion(D, Args, MArch, Name, Vers, Major, Minor))
+ return;
// Check if duplicated extension.
- if (llvm::is_contained(AllExts, Ext)) {
+ if (llvm::is_contained(AllExts, Name)) {
std::string Error = "duplicated ";
Error += Desc;
D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
- << MArch << Error << Ext;
+ << 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(Ext);
+ AllExts.push_back(Name);
}
// Set target features.
@@ -186,7 +256,10 @@ static void getExtensionFeatures(const Driver &D,
<< MArch << Error << Ext;
return;
}
- Features.push_back(Args.MakeArgString("+" + Ext));
+ if (isExperimentalExtension(Ext))
+ Features.push_back(Args.MakeArgString("+experimental-" + Ext));
+ else
+ Features.push_back(Args.MakeArgString("+" + Ext));
}
}
@@ -251,28 +324,35 @@ static bool getArchFeatures(const Driver &D, StringRef MArch,
// Skip rvxxx
StringRef Exts = MArch.substr(5);
- // Remove non-standard extensions and supervisor-level extensions.
- // They have 'x', 's', 'sx' prefixes. Parse them at the end.
- // Find the very first occurrence of 's' or 'x'.
+ // 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("sx");
+ 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, MArch, std::string(1, Baseline), Exts, 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
- // and consume the underscore '_' that might follow.
auto StdExtsItr = StdExts.begin();
auto StdExtsEnd = StdExts.end();
- for (auto I = Exts.begin(), E = Exts.end(); I != E; ++I) {
+ for (auto I = Exts.begin(), E = Exts.end(); I != E; ) {
char c = *I;
// Check ISA extensions are specified in the canonical order.
@@ -295,18 +375,15 @@ static bool getArchFeatures(const Driver &D, StringRef MArch,
// Move to next char to prevent repeated letter.
++StdExtsItr;
- if (std::next(I) != E) {
- // Skip c.
- std::string Next = std::string(std::next(I), E);
- std::string Major, Minor;
- if (!getExtensionVersion(D, MArch, std::string(1, c), Next, Major, Minor))
- return false;
-
- // TODO: Use version number when setting target features
- // and consume the underscore '_' that might follow.
- }
+ 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".
@@ -331,7 +408,22 @@ static bool getArchFeatures(const Driver &D, StringRef MArch,
case 'c':
Features.push_back("+c");
break;
+ case 'b':
+ Features.push_back("+experimental-b");
+ break;
+ case 'v':
+ Features.push_back("+experimental-v");
+ break;
}
+
+ // Consume full extension name and version, including any optional '_'
+ // between this extension and the next
+ ++I;
+ I += Major.size();
+ if (Minor.size())
+ I += Minor.size() + 1 /*'p'*/;
+ if (*I == '_')
+ ++I;
}
// Dependency check.
@@ -433,12 +525,11 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
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)) {
- // ... but we don't support -msave-restore, so issue a warning.
- D.Diag(diag::warn_drv_clang_unsupported)
- << Args.getLastArg(options::OPT_msave_restore)->getAsString(Args);
- }
+ // 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");
// Now add any that the user explicitly requested on the command line,
// which may override the defaults.
diff --git a/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp b/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp
index 2b77d59fdc66b..f81bf68172de1 100644
--- a/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp
@@ -7,6 +7,8 @@
//===----------------------------------------------------------------------===//
#include "SystemZ.h"
+#include "clang/Config/config.h"
+#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/Host.h"
@@ -16,24 +18,40 @@ using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;
+systemz::FloatABI systemz::getSystemZFloatABI(const Driver &D,
+ const ArgList &Args) {
+ // Hard float is the default.
+ systemz::FloatABI ABI = systemz::FloatABI::Hard;
+ if (Args.hasArg(options::OPT_mfloat_abi_EQ))
+ D.Diag(diag::err_drv_unsupported_opt)
+ << Args.getLastArg(options::OPT_mfloat_abi_EQ)->getAsString(Args);
+
+ if (Arg *A = Args.getLastArg(clang::driver::options::OPT_msoft_float,
+ options::OPT_mhard_float))
+ if (A->getOption().matches(clang::driver::options::OPT_msoft_float))
+ ABI = systemz::FloatABI::Soft;
+
+ return ABI;
+}
+
std::string systemz::getSystemZTargetCPU(const ArgList &Args) {
if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ)) {
llvm::StringRef CPUName = A->getValue();
if (CPUName == "native") {
- std::string CPU = llvm::sys::getHostCPUName();
+ std::string CPU = std::string(llvm::sys::getHostCPUName());
if (!CPU.empty() && CPU != "generic")
return CPU;
else
return "";
}
- return CPUName;
+ return std::string(CPUName);
}
- return "z10";
+ return CLANG_SYSTEMZ_DEFAULT_ARCH;
}
-void systemz::getSystemZTargetFeatures(const ArgList &Args,
+void systemz::getSystemZTargetFeatures(const Driver &D, const ArgList &Args,
std::vector<llvm::StringRef> &Features) {
// -m(no-)htm overrides use of the transactional-execution facility.
if (Arg *A = Args.getLastArg(options::OPT_mhtm, options::OPT_mno_htm)) {
@@ -49,4 +67,8 @@ void systemz::getSystemZTargetFeatures(const ArgList &Args,
else
Features.push_back("-vector");
}
+
+ systemz::FloatABI FloatABI = systemz::getSystemZFloatABI(D, Args);
+ if (FloatABI == systemz::FloatABI::Soft)
+ Features.push_back("+soft-float");
}
diff --git a/clang/lib/Driver/ToolChains/Arch/SystemZ.h b/clang/lib/Driver/ToolChains/Arch/SystemZ.h
index 77dcbc47be5c0..1e42b68a8f3c2 100644
--- a/clang/lib/Driver/ToolChains/Arch/SystemZ.h
+++ b/clang/lib/Driver/ToolChains/Arch/SystemZ.h
@@ -9,6 +9,7 @@
#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_SYSTEMZ_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_SYSTEMZ_H
+#include "clang/Driver/Driver.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Option/Option.h"
#include <string>
@@ -19,9 +20,16 @@ namespace driver {
namespace tools {
namespace systemz {
+enum class FloatABI {
+ Soft,
+ Hard,
+};
+
+FloatABI getSystemZFloatABI(const Driver &D, const llvm::opt::ArgList &Args);
+
std::string getSystemZTargetCPU(const llvm::opt::ArgList &Args);
-void getSystemZTargetFeatures(const llvm::opt::ArgList &Args,
+void getSystemZTargetFeatures(const Driver &D, const llvm::opt::ArgList &Args,
std::vector<llvm::StringRef> &Features);
} // end namespace systemz
diff --git a/clang/lib/Driver/ToolChains/Arch/VE.cpp b/clang/lib/Driver/ToolChains/Arch/VE.cpp
new file mode 100644
index 0000000000000..fa10e4810f1c9
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/Arch/VE.cpp
@@ -0,0 +1,26 @@
+//===--- VE.cpp - Tools 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 "VE.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"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+const char *ve::getVEAsmModeForCPU(StringRef Name, const llvm::Triple &Triple) {
+ return "";
+}
+
+void ve::getVETargetFeatures(const Driver &D, const ArgList &Args,
+ std::vector<StringRef> &Features) {}
diff --git a/clang/lib/Driver/ToolChains/Arch/VE.h b/clang/lib/Driver/ToolChains/Arch/VE.h
new file mode 100644
index 0000000000000..713e3e7d042f2
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/Arch/VE.h
@@ -0,0 +1,33 @@
+//===--- VE.h - VE-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_VE_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_VE_H
+
+#include "clang/Driver/Driver.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/Option.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace driver {
+namespace tools {
+namespace ve {
+
+void getVETargetFeatures(const Driver &D, const llvm::opt::ArgList &Args,
+ std::vector<llvm::StringRef> &Features);
+const char *getVEAsmModeForCPU(llvm::StringRef Name,
+ const llvm::Triple &Triple);
+
+} // end namespace ve
+} // namespace tools
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_VE_H
diff --git a/clang/lib/Driver/ToolChains/Arch/X86.cpp b/clang/lib/Driver/ToolChains/Arch/X86.cpp
index d1e0c8253b799..2cc44c09917f5 100644
--- a/clang/lib/Driver/ToolChains/Arch/X86.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/X86.cpp
@@ -31,7 +31,7 @@ const char *x86::getX86TargetCPU(const ArgList &Args,
//
// FIXME: We should also incorporate the detected target features for use
// with -native.
- std::string CPU = llvm::sys::getHostCPUName();
+ std::string CPU = std::string(llvm::sys::getHostCPUName());
if (!CPU.empty() && CPU != "generic")
return Args.MakeArgString(CPU);
}
@@ -94,6 +94,7 @@ const char *x86::getX86TargetCPU(const ArgList &Args,
switch (Triple.getOS()) {
case llvm::Triple::FreeBSD:
+ return "i686";
case llvm::Triple::NetBSD:
case llvm::Triple::OpenBSD:
return "i486";
@@ -146,6 +147,7 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
// flags). This is a bit hacky but keeps existing usages working. We should
// consider deprecating this and instead warn if the user requests external
// retpoline thunks and *doesn't* request some form of retpolines.
+ auto SpectreOpt = clang::driver::options::ID::OPT_INVALID;
if (Args.hasArgNoClaim(options::OPT_mretpoline, options::OPT_mno_retpoline,
options::OPT_mspeculative_load_hardening,
options::OPT_mno_speculative_load_hardening)) {
@@ -153,12 +155,14 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
false)) {
Features.push_back("+retpoline-indirect-calls");
Features.push_back("+retpoline-indirect-branches");
+ SpectreOpt = options::OPT_mretpoline;
} else if (Args.hasFlag(options::OPT_mspeculative_load_hardening,
options::OPT_mno_speculative_load_hardening,
false)) {
// On x86, speculative load hardening relies on at least using retpolines
// for indirect calls.
Features.push_back("+retpoline-indirect-calls");
+ SpectreOpt = options::OPT_mspeculative_load_hardening;
}
} else if (Args.hasFlag(options::OPT_mretpoline_external_thunk,
options::OPT_mno_retpoline_external_thunk, false)) {
@@ -166,6 +170,44 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
// eventually switch to an error here.
Features.push_back("+retpoline-indirect-calls");
Features.push_back("+retpoline-indirect-branches");
+ SpectreOpt = options::OPT_mretpoline_external_thunk;
+ }
+
+ auto LVIOpt = clang::driver::options::ID::OPT_INVALID;
+ if (Args.hasFlag(options::OPT_mlvi_hardening, options::OPT_mno_lvi_hardening,
+ false)) {
+ Features.push_back("+lvi-load-hardening");
+ Features.push_back("+lvi-cfi"); // load hardening implies CFI protection
+ LVIOpt = options::OPT_mlvi_hardening;
+ } else if (Args.hasFlag(options::OPT_mlvi_cfi, options::OPT_mno_lvi_cfi,
+ false)) {
+ Features.push_back("+lvi-cfi");
+ LVIOpt = options::OPT_mlvi_cfi;
+ }
+
+ if (Args.hasFlag(options::OPT_m_seses, options::OPT_mno_seses, false)) {
+ if (LVIOpt == options::OPT_mlvi_hardening)
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << D.getOpts().getOptionName(options::OPT_mlvi_hardening)
+ << D.getOpts().getOptionName(options::OPT_m_seses);
+
+ if (SpectreOpt != clang::driver::options::ID::OPT_INVALID)
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << D.getOpts().getOptionName(SpectreOpt)
+ << D.getOpts().getOptionName(options::OPT_m_seses);
+
+ Features.push_back("+seses");
+ if (!Args.hasArg(options::OPT_mno_lvi_cfi)) {
+ Features.push_back("+lvi-cfi");
+ LVIOpt = options::OPT_mlvi_cfi;
+ }
+ }
+
+ if (SpectreOpt != clang::driver::options::ID::OPT_INVALID &&
+ LVIOpt != clang::driver::options::ID::OPT_INVALID) {
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << D.getOpts().getOptionName(SpectreOpt)
+ << D.getOpts().getOptionName(LVIOpt);
}
// Now add any that the user explicitly requested on the command line,
diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp
index dff0e04183ef9..97cfa7d0e1569 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -67,7 +67,7 @@ Tool *BareMetal::buildLinker() const {
std::string BareMetal::getRuntimesDir() const {
SmallString<128> Dir(getDriver().ResourceDir);
llvm::sys::path::append(Dir, "lib", "baremetal");
- return Dir.str();
+ return std::string(Dir.str());
}
void BareMetal::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
@@ -157,7 +157,7 @@ void BareMetal::AddCXXStdlibLibArgs(const ArgList &Args,
void BareMetal::AddLinkRuntimeLib(const ArgList &Args,
ArgStringList &CmdArgs) const {
CmdArgs.push_back(Args.MakeArgString("-lclang_rt.builtins-" +
- getTriple().getArchName() + ".a"));
+ getTriple().getArchName()));
}
void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -191,7 +191,7 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- C.addCommand(std::make_unique<Command>(JA, *this,
- Args.MakeArgString(TC.GetLinkerPath()),
- CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Args.MakeArgString(TC.GetLinkerPath()),
+ CmdArgs, Inputs));
}
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 9b3055413e9e6..9d6333bb5f1dd 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "Clang.h"
+#include "AMDGPU.h"
#include "Arch/AArch64.h"
#include "Arch/ARM.h"
#include "Arch/Mips.h"
@@ -14,12 +15,12 @@
#include "Arch/RISCV.h"
#include "Arch/Sparc.h"
#include "Arch/SystemZ.h"
+#include "Arch/VE.h"
#include "Arch/X86.h"
-#include "AMDGPU.h"
#include "CommonArgs.h"
#include "Hexagon.h"
-#include "MSP430.h"
#include "InputInfo.h"
+#include "MSP430.h"
#include "PS4CPU.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/CodeGenOptions.h"
@@ -35,6 +36,7 @@
#include "llvm/Config/llvm-config.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/CodeGen.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -307,10 +309,9 @@ static void getWebAssemblyTargetFeatures(const ArgList &Args,
handleTargetFeaturesGroup(Args, Features, options::OPT_m_wasm_Features_Group);
}
-static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
+static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args, ArgStringList &CmdArgs,
- bool ForAS) {
- const Driver &D = TC.getDriver();
+ bool ForAS, bool IsAux = false) {
std::vector<StringRef> Features;
switch (Triple.getArch()) {
default:
@@ -326,7 +327,7 @@ static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
- arm::getARMTargetFeatures(TC, Triple, Args, CmdArgs, Features, ForAS);
+ arm::getARMTargetFeatures(D, Triple, Args, CmdArgs, Features, ForAS);
break;
case llvm::Triple::ppc:
@@ -339,7 +340,7 @@ static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
riscv::getRISCVTargetFeatures(D, Triple, Args, Features);
break;
case llvm::Triple::systemz:
- systemz::getSystemZTargetFeatures(Args, Features);
+ systemz::getSystemZTargetFeatures(D, Args, Features);
break;
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_32:
@@ -368,27 +369,14 @@ static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
break;
case llvm::Triple::msp430:
msp430::getMSP430TargetFeatures(D, Args, Features);
+ break;
+ case llvm::Triple::ve:
+ ve::getVETargetFeatures(D, Args, Features);
}
- // 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;
- }
-
- 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;
-
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back(Name.data());
+ for (auto Feature : unifyTargetFeatures(Features)) {
+ CmdArgs.push_back(IsAux ? "-aux-target-feature" : "-target-feature");
+ CmdArgs.push_back(Feature.data());
}
}
@@ -464,6 +452,11 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType,
}
}
+ // OPT_fignore_exceptions means exception could still be thrown,
+ // but no clean up or catch would happen in current module.
+ // So we do not set EH to false.
+ Args.AddLastArg(CmdArgs, options::OPT_fignore_exceptions);
+
if (EH)
CmdArgs.push_back("-fexceptions");
}
@@ -505,7 +498,7 @@ static codegenoptions::DebugInfoKind DebugLevelToInfoKind(const Arg &A) {
return codegenoptions::DebugLineTablesOnly;
if (A.getOption().matches(options::OPT_gline_directives_only))
return codegenoptions::DebugDirectivesOnly;
- return codegenoptions::LimitedDebugInfo;
+ return codegenoptions::DebugInfoConstructor;
}
static bool mustUseNonLeafFramePointerForTarget(const llvm::Triple &Triple) {
@@ -522,7 +515,7 @@ static bool mustUseNonLeafFramePointerForTarget(const llvm::Triple &Triple) {
static bool useFramePointerForTargetByDefault(const ArgList &Args,
const llvm::Triple &Triple) {
- if (Args.hasArg(options::OPT_pg))
+ if (Args.hasArg(options::OPT_pg) && !Args.hasArg(options::OPT_mfentry))
return true;
switch (Triple.getArch()) {
@@ -553,6 +546,13 @@ static bool useFramePointerForTargetByDefault(const ArgList &Args,
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:
@@ -721,38 +721,6 @@ static void addDashXForInput(const ArgList &Args, const InputInfo &Input,
}
}
-static void appendUserToPath(SmallVectorImpl<char> &Result) {
-#ifdef LLVM_ON_UNIX
- const char *Username = getenv("LOGNAME");
-#else
- const char *Username = getenv("USERNAME");
-#endif
- if (Username) {
- // Validate that LoginName can be used in a path, and get its length.
- size_t Len = 0;
- for (const char *P = Username; *P; ++P, ++Len) {
- if (!clang::isAlphanumeric(*P) && *P != '_') {
- Username = nullptr;
- break;
- }
- }
-
- if (Username && Len > 0) {
- Result.append(Username, Username + Len);
- return;
- }
- }
-
-// Fallback to user id.
-#ifdef LLVM_ON_UNIX
- std::string UID = llvm::utostr(getuid());
-#else
- // FIXME: Windows seems to have an 'SID' that might work.
- std::string UID = "9999";
-#endif
- Result.append(UID.begin(), UID.end());
-}
-
static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C,
const Driver &D, const InputInfo &Output,
const ArgList &Args,
@@ -808,8 +776,8 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C,
CmdArgs.push_back("-fprofile-instrument=clang");
if (TC.getTriple().isWindowsMSVCEnvironment()) {
// Add dependent lib for clang_rt.profile
- CmdArgs.push_back(Args.MakeArgString("--dependent-lib=" +
- TC.getCompilerRT(Args, "profile")));
+ CmdArgs.push_back(Args.MakeArgString(
+ "--dependent-lib=" + TC.getCompilerRTBasename(Args, "profile")));
}
}
@@ -826,8 +794,9 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C,
}
if (PGOGenArg) {
if (TC.getTriple().isWindowsMSVCEnvironment()) {
- CmdArgs.push_back(Args.MakeArgString("--dependent-lib=" +
- TC.getCompilerRT(Args, "profile")));
+ // Add dependent lib for clang_rt.profile
+ CmdArgs.push_back(Args.MakeArgString(
+ "--dependent-lib=" + TC.getCompilerRTBasename(Args, "profile")));
}
if (PGOGenArg->getOption().matches(
PGOGenerateArg ? options::OPT_fprofile_generate_EQ
@@ -856,11 +825,10 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C,
}
}
- bool EmitCovNotes = Args.hasArg(options::OPT_ftest_coverage) ||
+ bool EmitCovNotes = Args.hasFlag(options::OPT_ftest_coverage,
+ options::OPT_fno_test_coverage, false) ||
Args.hasArg(options::OPT_coverage);
- bool EmitCovData = Args.hasFlag(options::OPT_fprofile_arcs,
- options::OPT_fno_profile_arcs, false) ||
- Args.hasArg(options::OPT_coverage);
+ bool EmitCovData = TC.needsGCovInstrumentation(Args);
if (EmitCovNotes)
CmdArgs.push_back("-femit-coverage-notes");
if (EmitCovData)
@@ -1190,12 +1158,14 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_MP);
Args.AddLastArg(CmdArgs, options::OPT_MV);
- // Add offload include arguments specific for CUDA. This must happen before
- // we -I or -include anything else, because we must pick up the CUDA headers
- // from the particular CUDA installation, rather than from e.g.
- // /usr/local/include.
+ // Add offload include arguments specific for CUDA/HIP. This must happen
+ // before we -I or -include anything else, because we must pick up the
+ // CUDA/HIP headers from the particular CUDA/ROCm installation, rather than
+ // from e.g. /usr/local/include.
if (JA.isOffloading(Action::OFK_Cuda))
getToolChain().AddCudaIncludeArgs(Args, CmdArgs);
+ if (JA.isOffloading(Action::OFK_HIP))
+ getToolChain().AddHIPIncludeArgs(Args, CmdArgs);
// If we are offloading to a target via OpenMP we need to include the
// openmp_wrappers folder which contains alternative system headers.
@@ -1212,7 +1182,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
}
CmdArgs.push_back("-include");
- CmdArgs.push_back("__clang_openmp_math_declares.h");
+ CmdArgs.push_back("__clang_openmp_device_functions.h");
}
// Add -i* options, and automatically translate to
@@ -1227,6 +1197,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
if (YcArg && JA.getKind() >= Action::PrecompileJobClass &&
JA.getKind() <= Action::AssembleJobClass) {
CmdArgs.push_back(Args.MakeArgString("-building-pch-with-obj"));
+ CmdArgs.push_back(Args.MakeArgString("-fpch-instantiate-templates"));
}
if (YcArg || YuArg) {
StringRef ThroughHeader = YcArg ? YcArg->getValue() : YuArg->getValue();
@@ -1404,20 +1375,6 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) {
}
}
-static bool isNoCommonDefault(const llvm::Triple &Triple) {
- switch (Triple.getArch()) {
- default:
- if (Triple.isOSFuchsia())
- return true;
- return false;
-
- case llvm::Triple::xcore:
- case llvm::Triple::wasm32:
- case llvm::Triple::wasm64:
- return true;
- }
-}
-
static bool hasMultipleInvocations(const llvm::Triple &Triple,
const ArgList &Args) {
// Supported only on Darwin where we invoke the compiler multiple times
@@ -1594,7 +1551,7 @@ void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple,
const ToolChain &TC = getToolChain();
// Add the target features
- getTargetFeatures(TC, EffectiveTriple, Args, CmdArgs, false);
+ getTargetFeatures(TC.getDriver(), EffectiveTriple, Args, CmdArgs, false);
// Add target specific flags.
switch (TC.getArch()) {
@@ -1662,6 +1619,10 @@ void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple,
case llvm::Triple::wasm64:
AddWebAssemblyTargetArgs(Args, CmdArgs);
break;
+
+ case llvm::Triple::ve:
+ AddVETargetArgs(Args, CmdArgs);
+ break;
}
}
@@ -1970,6 +1931,36 @@ void Clang::AddPPCTargetArgs(const ArgList &Args,
}
}
+static void SetRISCVSmallDataLimit(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ const Driver &D = TC.getDriver();
+ const llvm::Triple &Triple = TC.getTriple();
+ // Default small data limitation is eight.
+ const char *SmallDataLimit = "8";
+ // Get small data limitation.
+ if (Args.getLastArg(options::OPT_shared, options::OPT_fpic,
+ options::OPT_fPIC)) {
+ // Not support linker relaxation for PIC.
+ SmallDataLimit = "0";
+ if (Args.hasArg(options::OPT_G)) {
+ D.Diag(diag::warn_drv_unsupported_sdata);
+ }
+ } else if (Args.getLastArgValue(options::OPT_mcmodel_EQ)
+ .equals_lower("large") &&
+ (Triple.getArch() == llvm::Triple::riscv64)) {
+ // Not support linker relaxation for RV64 with large code model.
+ 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();
+ }
+ // Forward the -msmall-data-limit= option.
+ CmdArgs.push_back("-msmall-data-limit");
+ CmdArgs.push_back(SmallDataLimit);
+}
+
void Clang::AddRISCVTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
const llvm::Triple &Triple = getToolChain().getTriple();
@@ -1977,6 +1968,8 @@ void Clang::AddRISCVTargetArgs(const ArgList &Args,
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName.data());
+
+ SetRISCVSmallDataLimit(getToolChain(), Args, CmdArgs);
}
void Clang::AddSparcTargetArgs(const ArgList &Args,
@@ -2003,70 +1996,30 @@ void Clang::AddSystemZTargetArgs(const ArgList &Args,
options::OPT_mno_backchain, false);
bool HasPackedStack = Args.hasFlag(options::OPT_mpacked_stack,
options::OPT_mno_packed_stack, false);
- if (HasBackchain && HasPackedStack) {
+ systemz::FloatABI FloatABI =
+ systemz::getSystemZFloatABI(getToolChain().getDriver(), Args);
+ bool HasSoftFloat = (FloatABI == systemz::FloatABI::Soft);
+ if (HasBackchain && HasPackedStack && !HasSoftFloat) {
const Driver &D = getToolChain().getDriver();
D.Diag(diag::err_drv_unsupported_opt)
- << Args.getLastArg(options::OPT_mpacked_stack)->getAsString(Args) +
- " " + Args.getLastArg(options::OPT_mbackchain)->getAsString(Args);
+ << "-mpacked-stack -mbackchain -mhard-float";
}
if (HasBackchain)
CmdArgs.push_back("-mbackchain");
if (HasPackedStack)
CmdArgs.push_back("-mpacked-stack");
-}
-
-static void addX86AlignBranchArgs(const Driver &D, const ArgList &Args,
- ArgStringList &CmdArgs) {
- if (Args.hasArg(options::OPT_mbranches_within_32B_boundaries)) {
- CmdArgs.push_back("-mllvm");
- CmdArgs.push_back("-x86-branches-within-32B-boundaries");
- }
- if (const Arg *A = Args.getLastArg(options::OPT_malign_branch_boundary_EQ)) {
- StringRef Value = A->getValue();
- unsigned Boundary;
- if (Value.getAsInteger(10, Boundary) || Boundary < 16 ||
- !llvm::isPowerOf2_64(Boundary)) {
- D.Diag(diag::err_drv_invalid_argument_to_option)
- << Value << A->getOption().getName();
- } else {
- CmdArgs.push_back("-mllvm");
- CmdArgs.push_back(
- Args.MakeArgString("-x86-align-branch-boundary=" + Twine(Boundary)));
- }
- }
- if (const Arg *A = Args.getLastArg(options::OPT_malign_branch_EQ)) {
- std::string AlignBranch;
- for (StringRef T : A->getValues()) {
- if (T != "fused" && T != "jcc" && T != "jmp" && T != "call" &&
- T != "ret" && T != "indirect")
- D.Diag(diag::err_drv_invalid_malign_branch_EQ)
- << T << "fused, jcc, jmp, call, ret, indirect";
- if (!AlignBranch.empty())
- AlignBranch += '+';
- AlignBranch += T;
- }
- CmdArgs.push_back("-mllvm");
- CmdArgs.push_back(Args.MakeArgString("-x86-align-branch=" + AlignBranch));
- }
- if (const Arg *A =
- Args.getLastArg(options::OPT_malign_branch_prefix_size_EQ)) {
- StringRef Value = A->getValue();
- unsigned PrefixSize;
- if (Value.getAsInteger(10, PrefixSize) || PrefixSize > 5) {
- D.Diag(diag::err_drv_invalid_argument_to_option)
- << Value << A->getOption().getName();
- } else {
- CmdArgs.push_back("-mllvm");
- CmdArgs.push_back(Args.MakeArgString("-x86-align-branch-prefix-size=" +
- Twine(PrefixSize)));
- }
+ if (HasSoftFloat) {
+ // Floating point operations and argument passing are soft.
+ CmdArgs.push_back("-msoft-float");
+ CmdArgs.push_back("-mfloat-abi");
+ CmdArgs.push_back("soft");
}
}
void Clang::AddX86TargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
const Driver &D = getToolChain().getDriver();
- addX86AlignBranchArgs(D, Args, CmdArgs);
+ addX86AlignBranchArgs(D, Args, CmdArgs, /*IsLTO=*/false);
if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) ||
Args.hasArg(options::OPT_mkernel) ||
@@ -2167,6 +2120,12 @@ void Clang::AddWebAssemblyTargetArgs(const ArgList &Args,
}
}
+void Clang::AddVETargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const {
+ // Floating point operations and argument passing are hard.
+ CmdArgs.push_back("-mfloat-abi");
+ CmdArgs.push_back("hard");
+}
+
void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename,
StringRef Target, const InputInfo &Output,
const InputInfo &Input, const ArgList &Args) const {
@@ -2421,7 +2380,7 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
CmdArgs.push_back(Value.data());
} else {
RenderDebugEnablingArgs(Args, CmdArgs,
- codegenoptions::LimitedDebugInfo,
+ codegenoptions::DebugInfoConstructor,
DwarfVersion, llvm::DebuggerKind::Default);
}
} else if (Value.startswith("-mcpu") || Value.startswith("-mfpu") ||
@@ -2480,7 +2439,8 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
bool OFastEnabled, const ArgList &Args,
- ArgStringList &CmdArgs) {
+ ArgStringList &CmdArgs,
+ const JobAction &JA) {
// Handle various floating point optimization flags, mapping them to the
// appropriate LLVM code generation flags. This is complicated by several
// "umbrella" flags, so we do this by stepping through the flags incrementally
@@ -2502,10 +2462,17 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
StringRef FPModel = "";
// -ffp-exception-behavior options: strict, maytrap, ignore
StringRef FPExceptionBehavior = "";
- StringRef DenormalFPMath = "";
+ const llvm::DenormalMode DefaultDenormalFPMath =
+ TC.getDefaultDenormalModeForType(Args, JA);
+ const llvm::DenormalMode DefaultDenormalFP32Math =
+ TC.getDefaultDenormalModeForType(Args, JA, &llvm::APFloat::IEEEsingle());
+
+ llvm::DenormalMode DenormalFPMath = DefaultDenormalFPMath;
+ llvm::DenormalMode DenormalFP32Math = DefaultDenormalFP32Math;
StringRef FPContract = "";
bool StrictFPModel = false;
+
if (const Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
CmdArgs.push_back("-mlimit-float-precision");
CmdArgs.push_back(A->getValue());
@@ -2527,8 +2494,13 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
ReciprocalMath = false;
SignedZeros = true;
// -fno_fast_math restores default denormal and fpcontract handling
- DenormalFPMath = "";
FPContract = "";
+ DenormalFPMath = llvm::DenormalMode::getIEEE();
+
+ // FIXME: The target may have picked a non-IEEE default mode here based on
+ // -cl-denorms-are-zero. Should the target consider -fp-model interaction?
+ DenormalFP32Math = llvm::DenormalMode::getIEEE();
+
StringRef Val = A->getValue();
if (OFastEnabled && !Val.equals("fast")) {
// Only -ffp-model=fast is compatible with OFast, ignore.
@@ -2562,6 +2534,7 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
optID = options::OPT_frounding_math;
FPExceptionBehavior = "strict";
FPModel = Val;
+ FPContract = "off";
TrappingMath = true;
} else
D.Diag(diag::err_drv_unsupported_option_argument)
@@ -2621,7 +2594,19 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
break;
case options::OPT_fdenormal_fp_math_EQ:
- DenormalFPMath = A->getValue();
+ DenormalFPMath = llvm::parseDenormalFPAttribute(A->getValue());
+ if (!DenormalFPMath.isValid()) {
+ D.Diag(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << A->getValue();
+ }
+ break;
+
+ case options::OPT_fdenormal_fp_math_f32_EQ:
+ DenormalFP32Math = llvm::parseDenormalFPAttribute(A->getValue());
+ if (!DenormalFP32Math.isValid()) {
+ D.Diag(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << A->getValue();
+ }
break;
// Validate and pass through -ffp-contract option.
@@ -2690,8 +2675,10 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
SignedZeros = true;
TrappingMath = true;
FPExceptionBehavior = "strict";
- // -fno_unsafe_math_optimizations restores default denormal handling
- DenormalFPMath = "";
+
+ // The target may have opted to flush by default, so force IEEE.
+ DenormalFPMath = llvm::DenormalMode::getIEEE();
+ DenormalFP32Math = llvm::DenormalMode::getIEEE();
break;
case options::OPT_Ofast:
@@ -2724,7 +2711,8 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
TrappingMath = false;
RoundingFPMath = false;
// -fno_fast_math restores default denormal and fpcontract handling
- DenormalFPMath = "";
+ DenormalFPMath = DefaultDenormalFPMath;
+ DenormalFP32Math = llvm::DenormalMode::getIEEE();
FPContract = "";
break;
}
@@ -2734,7 +2722,9 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
if (HonorINFs && HonorNaNs &&
!AssociativeMath && !ReciprocalMath &&
SignedZeros && TrappingMath && RoundingFPMath &&
- DenormalFPMath.empty() && FPContract.empty())
+ (FPContract.equals("off") || FPContract.empty()) &&
+ DenormalFPMath == llvm::DenormalMode::getIEEE() &&
+ DenormalFP32Math == llvm::DenormalMode::getIEEE())
// OK: Current Arg doesn't conflict with -ffp-model=strict
;
else {
@@ -2780,9 +2770,21 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
} else if (TrappingMathPresent)
CmdArgs.push_back("-fno-trapping-math");
- if (!DenormalFPMath.empty())
- CmdArgs.push_back(
- Args.MakeArgString("-fdenormal-fp-math=" + DenormalFPMath));
+ // The default is IEEE.
+ if (DenormalFPMath != llvm::DenormalMode::getIEEE()) {
+ llvm::SmallString<64> DenormFlag;
+ llvm::raw_svector_ostream ArgStr(DenormFlag);
+ ArgStr << "-fdenormal-fp-math=" << DenormalFPMath;
+ CmdArgs.push_back(Args.MakeArgString(ArgStr.str()));
+ }
+
+ // Add f32 specific denormal mode flag if it's different.
+ if (DenormalFP32Math != DenormalFPMath) {
+ llvm::SmallString<64> DenormFlag;
+ llvm::raw_svector_ostream ArgStr(DenormFlag);
+ ArgStr << "-fdenormal-fp-math-f32=" << DenormalFP32Math;
+ CmdArgs.push_back(Args.MakeArgString(ArgStr.str()));
+ }
if (!FPContract.empty())
CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + FPContract));
@@ -2957,6 +2959,22 @@ static void RenderSSPOptions(const ToolChain &TC, const ArgList &Args,
}
}
+static void RenderSCPOptions(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ const llvm::Triple &EffectiveTriple = TC.getEffectiveTriple();
+
+ if (!EffectiveTriple.isOSLinux())
+ return;
+
+ if (!EffectiveTriple.isX86() && !EffectiveTriple.isSystemZ() &&
+ !EffectiveTriple.isPPC64())
+ return;
+
+ if (Args.hasFlag(options::OPT_fstack_clash_protection,
+ options::OPT_fnostack_clash_protection, false))
+ CmdArgs.push_back("-fstack-clash-protection");
+}
+
static void RenderTrivialAutoVarInitOptions(const Driver &D,
const ToolChain &TC,
const ArgList &Args,
@@ -2999,9 +3017,26 @@ static void RenderTrivialAutoVarInitOptions(const Driver &D,
CmdArgs.push_back(
Args.MakeArgString("-ftrivial-auto-var-init=" + TrivialAutoVarInit));
}
+
+ if (Arg *A =
+ Args.getLastArg(options::OPT_ftrivial_auto_var_init_stop_after)) {
+ 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_stop_after_missing_dependency);
+ A->claim();
+ StringRef Val = A->getValue();
+ if (std::stoi(Val.str()) <= 0)
+ D.Diag(diag::err_drv_trivial_auto_var_init_stop_after_invalid_value);
+ CmdArgs.push_back(
+ Args.MakeArgString("-ftrivial-auto-var-init-stop-after=" + Val));
+ }
}
static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs) {
+ // cl-denorms-are-zero is not forwarded. It is translated into a generic flag
+ // for denormal flushing handling based on the target.
const unsigned ForwardedArguments[] = {
options::OPT_cl_opt_disable,
options::OPT_cl_strict_aliasing,
@@ -3012,7 +3047,6 @@ static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs) {
options::OPT_cl_fast_relaxed_math,
options::OPT_cl_mad_enable,
options::OPT_cl_no_signed_zeros,
- options::OPT_cl_denorms_are_zero,
options::OPT_cl_fp32_correctly_rounded_divide_sqrt,
options::OPT_cl_uniform_work_group_size
};
@@ -3136,11 +3170,13 @@ static void RenderBuiltinOptions(const ToolChain &TC, const llvm::Triple &T,
CmdArgs.push_back("-fno-math-builtin");
}
-void Driver::getDefaultModuleCachePath(SmallVectorImpl<char> &Result) {
- llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false, Result);
- llvm::sys::path::append(Result, "org.llvm.clang.");
- appendUserToPath(Result);
- llvm::sys::path::append(Result, "ModuleCache");
+bool Driver::getDefaultModuleCachePath(SmallVectorImpl<char> &Result) {
+ if (llvm::sys::path::cache_directory(Result)) {
+ llvm::sys::path::append(Result, "clang");
+ llvm::sys::path::append(Result, "ModuleCache");
+ return true;
+ }
+ return false;
}
static void RenderModulesOptions(Compilation &C, const Driver &D,
@@ -3197,6 +3233,7 @@ static void RenderModulesOptions(Compilation &C, const Driver &D,
if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path))
Path = A->getValue();
+ bool HasPath = true;
if (C.isForDiagnostics()) {
// When generating crash reports, we want to emit the modules along with
// the reproduction sources, so we ignore any provided module path.
@@ -3205,12 +3242,16 @@ static void RenderModulesOptions(Compilation &C, const Driver &D,
llvm::sys::path::append(Path, "modules");
} else if (Path.empty()) {
// No module path was provided: use the default.
- Driver::getDefaultModuleCachePath(Path);
+ HasPath = Driver::getDefaultModuleCachePath(Path);
}
- const char Arg[] = "-fmodules-cache-path=";
- Path.insert(Path.begin(), Arg, Arg + strlen(Arg));
- CmdArgs.push_back(Args.MakeArgString(Path));
+ // `HasPath` will only be false if getDefaultModuleCachePath() fails.
+ // That being said, that failure is unlikely and not caching is harmless.
+ if (HasPath) {
+ const char Arg[] = "-fmodules-cache-path=";
+ Path.insert(Path.begin(), Arg, Arg + strlen(Arg));
+ CmdArgs.push_back(Args.MakeArgString(Path));
+ }
}
if (HaveModules) {
@@ -3469,9 +3510,9 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
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))
- CmdArgs.push_back("-fdiagnostics-show-option");
+ if (!Args.hasFlag(options::OPT_fdiagnostics_show_option,
+ options::OPT_fno_diagnostics_show_option, true))
+ CmdArgs.push_back("-fno-diagnostics-show-option");
if (const Arg *A =
Args.getLastArg(options::OPT_fdiagnostics_show_category_EQ)) {
@@ -3574,8 +3615,7 @@ static DwarfFissionKind getDebugFissionKind(const Driver &D,
static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
const llvm::Triple &T, const ArgList &Args,
- bool EmitCodeView, bool IsWindowsMSVC,
- ArgStringList &CmdArgs,
+ bool EmitCodeView, ArgStringList &CmdArgs,
codegenoptions::DebugInfoKind &DebugInfoKind,
DwarfFissionKind &DwarfFission) {
if (Args.hasFlag(options::OPT_fdebug_info_for_profiling,
@@ -3613,7 +3653,7 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
if (const Arg *A =
Args.getLastArg(options::OPT_g_Group, options::OPT_gsplit_dwarf,
options::OPT_gsplit_dwarf_EQ)) {
- DebugInfoKind = codegenoptions::LimitedDebugInfo;
+ DebugInfoKind = codegenoptions::DebugInfoConstructor;
// If the last option explicitly specified a debug-info level, use it.
if (checkDebugInfoOption(A, Args, D, TC) &&
@@ -3708,10 +3748,9 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
// not to include any column info.
if (const Arg *A = Args.getLastArg(options::OPT_gcolumn_info))
(void)checkDebugInfoOption(A, Args, D, TC);
- if (Args.hasFlag(options::OPT_gcolumn_info, options::OPT_gno_column_info,
- /*Default=*/!EmitCodeView &&
- DebuggerTuning != llvm::DebuggerKind::SCE))
- CmdArgs.push_back("-dwarf-column-info");
+ if (!Args.hasFlag(options::OPT_gcolumn_info, options::OPT_gno_column_info,
+ !EmitCodeView && DebuggerTuning != llvm::DebuggerKind::SCE))
+ 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.
@@ -3719,7 +3758,7 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
if (checkDebugInfoOption(A, Args, D, TC)) {
if (DebugInfoKind != codegenoptions::DebugLineTablesOnly &&
DebugInfoKind != codegenoptions::DebugDirectivesOnly) {
- DebugInfoKind = codegenoptions::LimitedDebugInfo;
+ DebugInfoKind = codegenoptions::DebugInfoConstructor;
CmdArgs.push_back("-dwarf-ext-refs");
CmdArgs.push_back("-fmodule-format=obj");
}
@@ -3739,7 +3778,9 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
TC.GetDefaultStandaloneDebug());
if (const Arg *A = Args.getLastArg(options::OPT_fstandalone_debug))
(void)checkDebugInfoOption(A, Args, D, TC);
- if (DebugInfoKind == codegenoptions::LimitedDebugInfo && NeedFullDebug)
+ if ((DebugInfoKind == codegenoptions::LimitedDebugInfo ||
+ DebugInfoKind == codegenoptions::DebugInfoConstructor) &&
+ NeedFullDebug)
DebugInfoKind = codegenoptions::FullDebugInfo;
if (Args.hasFlag(options::OPT_gembed_source, options::OPT_gno_embed_source,
@@ -3912,7 +3953,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- const llvm::Triple *AuxTriple = IsCuda ? TC.getAuxTriple() : nullptr;
+ const llvm::Triple *AuxTriple =
+ (IsCuda || IsHIP) ? TC.getAuxTriple() : nullptr;
bool IsWindowsMSVC = RawTriple.isWindowsMSVCEnvironment();
bool IsIAMCU = RawTriple.isOSIAMCU();
@@ -3977,6 +4019,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(NormalizedTriple));
}
+ if (Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false)) {
+ CmdArgs.push_back("-fsycl");
+ CmdArgs.push_back("-fsycl-is-device");
+
+ if (Arg *A = Args.getLastArg(options::OPT_sycl_std_EQ)) {
+ A->render(Args, CmdArgs);
+ } else {
+ // Ensure the default version in SYCL mode is 1.2.1 (aka 2017)
+ CmdArgs.push_back("-sycl-std=2017");
+ }
+ }
+
if (IsOpenMPDevice) {
// We have to pass the triple of the host if compiling for an OpenMP device.
std::string NormalizedTriple =
@@ -3990,9 +4044,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Triple.isOSWindows() && (Triple.getArch() == llvm::Triple::arm ||
Triple.getArch() == llvm::Triple::thumb)) {
unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6;
- unsigned Version;
- Triple.getArchName().substr(Offset).getAsInteger(10, Version);
- if (Version < 7)
+ unsigned Version = 0;
+ bool Failure =
+ Triple.getArchName().substr(Offset).consumeInteger(10, Version);
+ if (Failure || Version < 7)
D.Diag(diag::err_target_unsupported_arch) << Triple.getArchName()
<< TripleStr;
}
@@ -4083,7 +4138,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
StringRef ArgStr =
Args.hasArg(options::OPT_interface_stub_version_EQ)
? Args.getLastArgValue(options::OPT_interface_stub_version_EQ)
- : "experimental-ifs-v1";
+ : "experimental-ifs-v2";
CmdArgs.push_back("-emit-interface-stubs");
CmdArgs.push_back(
Args.MakeArgString(Twine("-interface-stub-version=") + ArgStr.str()));
@@ -4153,8 +4208,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_function_sections,
options::OPT_fdata_sections,
options::OPT_fno_data_sections,
+ options::OPT_fbasic_block_sections_EQ,
+ options::OPT_funique_internal_linkage_names,
+ options::OPT_fno_unique_internal_linkage_names,
options::OPT_funique_section_names,
options::OPT_fno_unique_section_names,
+ options::OPT_funique_basic_block_section_names,
+ options::OPT_fno_unique_basic_block_section_names,
options::OPT_mrestrict_it,
options::OPT_mno_restrict_it,
options::OPT_mstackrealign,
@@ -4195,7 +4255,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-mdisable-tail-calls");
RenderFloatingPointOptions(TC, D, isOptimizationLevelFast(Args), Args,
- CmdArgs);
+ CmdArgs, JA);
// Render ABI arguments
switch (TC.getArch()) {
@@ -4240,8 +4300,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
II.getInputArg().renderAsInput(Args, CmdArgs);
}
- C.addCommand(std::make_unique<Command>(JA, *this, D.getClangProgramPath(),
- CmdArgs, Inputs));
+ C.addCommand(
+ std::make_unique<Command>(JA, *this, ResponseFileSupport::AtFileUTF8(),
+ D.getClangProgramPath(), CmdArgs, Inputs));
return;
}
@@ -4266,8 +4327,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Discard value names in assert builds unless otherwise specified.
if (Args.hasFlag(options::OPT_fdiscard_value_names,
- options::OPT_fno_discard_value_names, !IsAssertBuild))
+ 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());
+ }))) {
+ D.Diag(diag::warn_ignoring_fdiscard_for_bitcode);
+ }
CmdArgs.push_back("-discard-value-names");
+ }
// Set the main file name, so that debug info works even with
// -save-temps.
@@ -4321,14 +4390,24 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
bool IsPIE;
std::tie(RelocationModel, PICLevel, IsPIE) = ParsePICArgs(TC, Args);
- const char *RMName = RelocationModelName(RelocationModel);
+ bool IsROPI = RelocationModel == llvm::Reloc::ROPI ||
+ RelocationModel == llvm::Reloc::ROPI_RWPI;
+ bool IsRWPI = RelocationModel == llvm::Reloc::RWPI ||
+ RelocationModel == llvm::Reloc::ROPI_RWPI;
- if ((RelocationModel == llvm::Reloc::ROPI ||
- RelocationModel == llvm::Reloc::ROPI_RWPI) &&
- types::isCXX(Input.getType()) &&
+ if (Args.hasArg(options::OPT_mcmse) &&
+ !Args.hasArg(options::OPT_fallow_unsupported)) {
+ if (IsROPI)
+ D.Diag(diag::err_cmse_pi_are_incompatible) << IsROPI;
+ if (IsRWPI)
+ D.Diag(diag::err_cmse_pi_are_incompatible) << !IsRWPI;
+ }
+
+ if (IsROPI && types::isCXX(Input.getType()) &&
!Args.hasArg(options::OPT_fallow_unsupported))
D.Diag(diag::err_drv_ropi_incompatible_with_cxx);
+ const char *RMName = RelocationModelName(RelocationModel);
if (RMName) {
CmdArgs.push_back("-mrelocation-model");
CmdArgs.push_back(RMName);
@@ -4352,15 +4431,27 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue());
}
- CmdArgs.push_back("-mthread-model");
- if (Arg *A = Args.getLastArg(options::OPT_mthread_model)) {
- if (!TC.isThreadModelSupported(A->getValue()))
- D.Diag(diag::err_drv_invalid_thread_model_for_target)
- << A->getValue() << A->getAsString(Args);
- CmdArgs.push_back(A->getValue());
+ // The default is -fno-semantic-interposition. We render it just because we
+ // require explicit -fno-semantic-interposition to infer dso_local.
+ if (Arg *A = Args.getLastArg(options::OPT_fsemantic_interposition,
+ options::OPT_fno_semantic_interposition))
+ if (RelocationModel != llvm::Reloc::Static && !IsPIE)
+ A->render(Args, CmdArgs);
+
+ {
+ std::string Model;
+ if (Arg *A = Args.getLastArg(options::OPT_mthread_model)) {
+ if (!TC.isThreadModelSupported(A->getValue()))
+ D.Diag(diag::err_drv_invalid_thread_model_for_target)
+ << A->getValue() << A->getAsString(Args);
+ Model = A->getValue();
+ } else
+ Model = TC.getThreadModel();
+ if (Model != "posix") {
+ CmdArgs.push_back("-mthread-model");
+ CmdArgs.push_back(Args.MakeArgString(Model));
+ }
}
- else
- CmdArgs.push_back(Args.MakeArgString(TC.getThreadModel()));
Args.AddLastArg(CmdArgs, options::OPT_fveclib);
@@ -4413,6 +4504,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue());
}
+ if (Arg *A = Args.getLastArg(options::OPT_maix_struct_return,
+ options::OPT_msvr4_struct_return)) {
+ if (TC.getArch() != llvm::Triple::ppc) {
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getSpelling() << RawTriple.str();
+ } else if (A->getOption().matches(options::OPT_maix_struct_return)) {
+ CmdArgs.push_back("-maix-struct-return");
+ } else {
+ assert(A->getOption().matches(options::OPT_msvr4_struct_return));
+ CmdArgs.push_back("-msvr4-struct-return");
+ }
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_fpcc_struct_return,
options::OPT_freg_struct_return)) {
if (TC.getArch() != llvm::Triple::x86) {
@@ -4429,6 +4533,13 @@ 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.hasArg(options::OPT_fenable_matrix)) {
+ // enable-matrix is needed by both the LangOpts and by LLVM.
+ CmdArgs.push_back("-fenable-matrix");
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-enable-matrix");
+ }
+
CodeGenOptions::FramePointerKind FPKeepKind =
getFramePointerKind(Args, RawTriple);
const char *FPKeepKindStr = nullptr;
@@ -4447,8 +4558,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(FPKeepKindStr);
if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss,
- options::OPT_fno_zero_initialized_in_bss))
- CmdArgs.push_back("-mno-zero-initialized-in-bss");
+ options::OPT_fno_zero_initialized_in_bss, true))
+ CmdArgs.push_back("-fno-zero-initialized-in-bss");
bool OFastEnabled = isOptimizationLevelFast(Args);
// If -Ofast is the optimization level, then -fstrict-aliasing should be
@@ -4495,7 +4606,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_fsplit_stack))
CmdArgs.push_back("-split-stacks");
- RenderFloatingPointOptions(TC, D, OFastEnabled, Args, CmdArgs);
+ RenderFloatingPointOptions(TC, D, OFastEnabled, Args, CmdArgs, JA);
+
+ if (Arg *A = Args.getLastArg(options::OPT_mdouble_EQ)) {
+ if (TC.getArch() == llvm::Triple::avr)
+ A->render(Args, CmdArgs);
+ else
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getAsString(Args) << TripleStr;
+ }
if (Arg *A = Args.getLastArg(options::OPT_LongDouble_Group)) {
if (TC.getTriple().isX86())
@@ -4511,9 +4630,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Decide whether to use verbose asm. Verbose assembly is the default on
// toolchains which have the integrated assembler on by default.
bool IsIntegratedAssemblerDefault = TC.IsIntegratedAssemblerDefault();
- if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,
- IsIntegratedAssemblerDefault))
- CmdArgs.push_back("-masm-verbose");
+ if (!Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,
+ IsIntegratedAssemblerDefault))
+ CmdArgs.push_back("-fno-verbose-asm");
if (!TC.useIntegratedAs())
CmdArgs.push_back("-no-integrated-as");
@@ -4529,8 +4648,8 @@ 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 device code, where
- // aliases aren't supported.
- if (!RawTriple.isOSDarwin() && !RawTriple.isNVPTX())
+ // aliases aren't supported. Similarly, aliases aren't yet supported for AIX.
+ if (!RawTriple.isOSDarwin() && !RawTriple.isNVPTX() && !RawTriple.isOSAIX())
CmdArgs.push_back("-mconstructor-aliases");
// Darwin's kernel doesn't support guard variables; just die if we
@@ -4539,7 +4658,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fforbid-guard-variables");
if (Args.hasFlag(options::OPT_mms_bitfields, options::OPT_mno_ms_bitfields,
- false)) {
+ Triple.isWindowsGNUEnvironment())) {
CmdArgs.push_back("-mms-bitfields");
}
@@ -4575,14 +4694,36 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
AsynchronousUnwindTables))
CmdArgs.push_back("-munwind-tables");
+ // Prepare `-aux-target-cpu` and `-aux-target-feature` unless
+ // `--gpu-use-aux-triple-only` is specified.
+ if (!Args.getLastArg(options::OPT_gpu_use_aux_triple_only) &&
+ ((IsCuda && JA.isDeviceOffloading(Action::OFK_Cuda)) ||
+ (IsHIP && JA.isDeviceOffloading(Action::OFK_HIP)))) {
+ const ArgList &HostArgs =
+ C.getArgsForToolChain(nullptr, StringRef(), Action::OFK_None);
+ std::string HostCPU =
+ getCPUName(HostArgs, *TC.getAuxTriple(), /*FromAs*/ false);
+ if (!HostCPU.empty()) {
+ CmdArgs.push_back("-aux-target-cpu");
+ CmdArgs.push_back(Args.MakeArgString(HostCPU));
+ }
+ getTargetFeatures(D, *TC.getAuxTriple(), HostArgs, CmdArgs,
+ /*ForAS*/ false, /*IsAux*/ true);
+ }
+
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)) {
- CmdArgs.push_back("-mcode-model");
- CmdArgs.push_back(A->getValue());
+ StringRef CM = A->getValue();
+ if (CM == "small" || CM == "kernel" || CM == "medium" || CM == "large" ||
+ CM == "tiny")
+ A->render(Args, CmdArgs);
+ else
+ D.Diag(diag::err_drv_invalid_argument_to_option)
+ << CM << A->getOption().getName();
}
if (Arg *A = Args.getLastArg(options::OPT_mtls_size_EQ)) {
@@ -4617,8 +4758,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
AddClangCLArgs(Args, InputType, CmdArgs, &DebugInfoKind, &EmitCodeView);
DwarfFissionKind DwarfFission;
- RenderDebugOptions(TC, D, RawTriple, Args, EmitCodeView, IsWindowsMSVC,
- CmdArgs, DebugInfoKind, DwarfFission);
+ RenderDebugOptions(TC, D, RawTriple, Args, EmitCodeView, CmdArgs,
+ DebugInfoKind, DwarfFission);
// Add the split debug info name to the command lines here so we
// can propagate it to the backend.
@@ -4664,11 +4805,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
Args.AddAllArgs(CmdArgs, options::OPT_v);
- Args.AddLastArg(CmdArgs, options::OPT_H);
+
+ if (Args.getLastArg(options::OPT_H)) {
+ CmdArgs.push_back("-H");
+ CmdArgs.push_back("-sys-header-deps");
+ }
+
if (D.CCPrintHeaders && !D.CCGenDiagnostics) {
CmdArgs.push_back("-header-include-file");
CmdArgs.push_back(D.CCPrintHeadersFilename ? D.CCPrintHeadersFilename
: "-");
+ CmdArgs.push_back("-sys-header-deps");
}
Args.AddLastArg(CmdArgs, options::OPT_P);
Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout);
@@ -4679,6 +4826,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
: "-");
}
+ // Give the gen diagnostics more chances to succeed, by avoiding intentional
+ // crashes.
+ if (D.CCGenDiagnostics)
+ CmdArgs.push_back("-disable-pragma-debug-crash");
+
bool UseSeparateSections = isUseSeparateSections(Triple);
if (Args.hasFlag(options::OPT_ffunction_sections,
@@ -4686,6 +4838,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-ffunction-sections");
}
+ if (Arg *A = Args.getLastArg(options::OPT_fbasic_block_sections_EQ)) {
+ StringRef Val = A->getValue();
+ if (Val != "all" && Val != "labels" && Val != "none" &&
+ !(Val.startswith("list=") && llvm::sys::fs::exists(Val.substr(5))))
+ D.Diag(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << A->getValue();
+ else
+ A->render(Args, CmdArgs);
+ }
+
if (Args.hasFlag(options::OPT_fdata_sections, options::OPT_fno_data_sections,
UseSeparateSections)) {
CmdArgs.push_back("-fdata-sections");
@@ -4695,14 +4857,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
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.AddLastArg(CmdArgs, options::OPT_finstrument_functions,
options::OPT_finstrument_functions_after_inlining,
options::OPT_finstrument_function_entry_bare);
- // NVPTX doesn't support PGO or coverage. There's no runtime support for
- // sampling, overhead of call arc collection is way too high and there's no
- // way to collect the output.
- if (!Triple.isNVPTX())
+ // NVPTX/AMDGCN doesn't support PGO or coverage. There's no runtime support
+ // 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);
Args.AddLastArg(CmdArgs, options::OPT_fclang_abi_compat_EQ);
@@ -4821,6 +4991,11 @@ 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:
@@ -4964,15 +5139,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
// Pass -fmessage-length=.
- CmdArgs.push_back("-fmessage-length");
+ unsigned MessageLength = 0;
if (Arg *A = Args.getLastArg(options::OPT_fmessage_length_EQ)) {
- CmdArgs.push_back(A->getValue());
+ StringRef V(A->getValue());
+ if (V.getAsInteger(0, MessageLength))
+ D.Diag(diag::err_drv_invalid_argument_to_option)
+ << V << A->getOption().getName();
} else {
// If -fmessage-length=N was not specified, determine whether this is a
// terminal and, if so, implicitly define -fmessage-length appropriately.
- unsigned N = llvm::sys::Process::StandardErrColumns();
- CmdArgs.push_back(Args.MakeArgString(Twine(N)));
+ MessageLength = llvm::sys::Process::StandardErrColumns();
}
+ if (MessageLength != 0)
+ CmdArgs.push_back(
+ Args.MakeArgString("-fmessage-length=" + Twine(MessageLength)));
// -fvisibility= and -fvisibility-ms-compat are of a piece.
if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ,
@@ -5001,7 +5181,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);
Args.AddLastArg(CmdArgs, options::OPT_femulated_tls,
options::OPT_fno_emulated_tls);
- Args.AddLastArg(CmdArgs, options::OPT_fkeep_static_consts);
// AltiVec-like language extensions aren't relevant for assembling.
if (!isa<PreprocessJobAction>(JA) || Output.getType() != types::TY_PP_Asm)
@@ -5047,6 +5226,13 @@ 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, forward
+ // cuda-parallel-target-regions flag
+ if (Args.hasFlag(options::OPT_fopenmp_cuda_parallel_target_regions,
+ options::OPT_fno_openmp_cuda_parallel_target_regions,
+ /*Default=*/true))
+ CmdArgs.push_back("-fopenmp-cuda-parallel-target-regions");
+
// When in OpenMP offloading mode with NVPTX target, check if full runtime
// is required.
if (Args.hasFlag(options::OPT_fopenmp_cuda_force_full_runtime,
@@ -5077,20 +5263,23 @@ 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, Start = 0;
+ unsigned Size, Offset = 0;
if (!Triple.isAArch64() && Triple.getArch() != llvm::Triple::x86 &&
Triple.getArch() != llvm::Triple::x86_64)
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getAsString(Args) << TripleStr;
else if (S.consumeInteger(10, Size) ||
(!S.empty() && (!S.consume_front(",") ||
- S.consumeInteger(10, Start) || !S.empty())))
+ S.consumeInteger(10, Offset) || !S.empty())))
D.Diag(diag::err_drv_invalid_argument_to_option)
<< S0 << A->getOption().getName();
- else if (Start)
+ else if (Size < Offset)
D.Diag(diag::err_drv_unsupported_fpatchable_function_entry_argument);
- else
+ else {
CmdArgs.push_back(Args.MakeArgString(A->getSpelling() + Twine(Size)));
+ CmdArgs.push_back(Args.MakeArgString(
+ "-fpatchable-function-entry-offset=" + Twine(Offset)));
+ }
}
if (TC.SupportsProfiling()) {
@@ -5164,11 +5353,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_pthread);
- if (Args.hasFlag(options::OPT_mspeculative_load_hardening, options::OPT_mno_speculative_load_hardening,
- false))
+ if (Args.hasFlag(options::OPT_mspeculative_load_hardening,
+ options::OPT_mno_speculative_load_hardening, false))
CmdArgs.push_back(Args.MakeArgString("-mspeculative-load-hardening"));
RenderSSPOptions(TC, Args, CmdArgs, KernelOrKext);
+ RenderSCPOptions(TC, Args, CmdArgs);
RenderTrivialAutoVarInitOptions(D, TC, Args, CmdArgs);
// Translate -mstackrealign
@@ -5214,8 +5404,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Forward -cl options to -cc1
RenderOpenCLOptions(Args, CmdArgs);
- if (Args.hasFlag(options::OPT_fhip_new_launch_api,
- options::OPT_fno_hip_new_launch_api, false))
+ if (IsHIP && Args.hasFlag(options::OPT_fhip_new_launch_api,
+ options::OPT_fno_hip_new_launch_api, true))
CmdArgs.push_back("-fhip-new-launch-api");
if (Arg *A = Args.getLastArg(options::OPT_fcf_protection_EQ)) {
@@ -5299,7 +5489,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fuse-cxa-atexit is default.
if (!Args.hasFlag(
options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit,
- !RawTriple.isOSWindows() &&
+ !RawTriple.isOSAIX() && !RawTriple.isOSWindows() &&
TC.getArch() != llvm::Triple::xcore &&
((RawTriple.getVendor() != llvm::Triple::MipsTechnologies) ||
RawTriple.hasEnvironment())) ||
@@ -5311,16 +5501,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
RawTriple.isOSDarwin() && !KernelOrKext))
CmdArgs.push_back("-fregister-global-dtors-with-atexit");
- // -fms-extensions=0 is default.
- if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
- IsWindowsMSVC))
- CmdArgs.push_back("-fms-extensions");
-
// -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");
+ // -fms-extensions=0 is default.
+ if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
+ IsWindowsMSVC))
+ CmdArgs.push_back("-fms-extensions");
+
// -fms-compatibility=0 is default.
bool IsMSVCCompat = Args.hasFlag(
options::OPT_fms_compatibility, options::OPT_fno_ms_compatibility,
@@ -5434,11 +5624,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasFlag(options::OPT_fpch_validate_input_files_content,
options::OPT_fno_pch_validate_input_files_content, false))
CmdArgs.push_back("-fvalidate-ast-input-files-content");
+ if (Args.hasFlag(options::OPT_fpch_instantiate_templates,
+ options::OPT_fno_pch_instantiate_templates, false))
+ CmdArgs.push_back("-fpch-instantiate-templates");
Args.AddLastArg(CmdArgs, options::OPT_fexperimental_new_pass_manager,
options::OPT_fno_experimental_new_pass_manager);
- ObjCRuntime Runtime = AddObjCRuntimeArgs(Args, CmdArgs, rewriteKind);
+ ObjCRuntime Runtime = AddObjCRuntimeArgs(Args, Inputs, CmdArgs, rewriteKind);
RenderObjCOptions(TC, D, RawTriple, Args, Runtime, rewriteKind != RK_None,
Input, CmdArgs);
@@ -5558,11 +5751,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasFlag(options::OPT_Qy, options::OPT_Qn, true))
CmdArgs.push_back("-Qn");
- // -fcommon is the default unless compiling kernel code or the target says so
- bool NoCommonDefault = KernelOrKext || isNoCommonDefault(RawTriple);
- if (!Args.hasFlag(options::OPT_fcommon, options::OPT_fno_common,
- !NoCommonDefault))
- CmdArgs.push_back("-fno-common");
+ // -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");
// -fsigned-bitfields is default, and clang doesn't yet support
// -funsigned-bitfields.
@@ -5680,6 +5871,8 @@ 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_fmax_tokens_EQ);
+
// Handle serialized diagnostics.
if (Arg *A = Args.getLastArg(options::OPT__serialize_diags)) {
CmdArgs.push_back("-serialize-diagnostic-file");
@@ -5749,7 +5942,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// FIXME: -fembed-bitcode -save-temps will save optimized bitcode instead of
// pristine IR generated by the frontend. Ideally, a new compile action should
// be added so both IR can be captured.
- if (C.getDriver().isSaveTempsEnabled() &&
+ if ((C.getDriver().isSaveTempsEnabled() ||
+ JA.isHostOffloading(Action::OFK_OpenMP)) &&
!(C.getDriver().embedBitcodeInObject() && !C.getDriver().isUsingLTO()) &&
isa<CompileJobAction>(JA))
CmdArgs.push_back("-disable-llvm-passes");
@@ -5779,7 +5973,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Arg->render(Args, OriginalArgs);
SmallString<256> Flags;
- Flags += Exec;
+ EscapeSpacesAndBackslashes(Exec, Flags);
for (const char *OriginalArg : OriginalArgs) {
SmallString<128> EscapedArg;
EscapeSpacesAndBackslashes(OriginalArg, EscapedArg);
@@ -5891,10 +6085,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (SplitLTOUnit)
CmdArgs.push_back("-fsplit-lto-unit");
- if (Arg *A = Args.getLastArg(options::OPT_fexperimental_isel,
- options::OPT_fno_experimental_isel)) {
+ if (Arg *A = Args.getLastArg(options::OPT_fglobal_isel,
+ options::OPT_fno_global_isel)) {
CmdArgs.push_back("-mllvm");
- if (A->getOption().matches(options::OPT_fexperimental_isel)) {
+ if (A->getOption().matches(options::OPT_fglobal_isel)) {
CmdArgs.push_back("-global-isel=1");
// GISel is on by default on AArch64 -O0, so don't bother adding
@@ -5913,9 +6107,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-global-isel-abort=2");
if (!IsArchSupported)
- D.Diag(diag::warn_drv_experimental_isel_incomplete) << Triple.getArchName();
+ D.Diag(diag::warn_drv_global_isel_incomplete) << Triple.getArchName();
else
- D.Diag(diag::warn_drv_experimental_isel_incomplete_opt);
+ D.Diag(diag::warn_drv_global_isel_incomplete_opt);
}
} else {
CmdArgs.push_back("-global-isel=0");
@@ -5939,6 +6133,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fforce-enable-int128");
}
+ if (Args.hasFlag(options::OPT_fkeep_static_consts,
+ options::OPT_fno_keep_static_consts, false))
+ CmdArgs.push_back("-fkeep-static-consts");
+
if (Args.hasFlag(options::OPT_fcomplete_member_pointers,
options::OPT_fno_complete_member_pointers, false))
CmdArgs.push_back("-fcomplete-member-pointers");
@@ -5950,11 +6148,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Arg *A = Args.getLastArg(options::OPT_moutline,
options::OPT_mno_outline)) {
if (A->getOption().matches(options::OPT_moutline)) {
- // We only support -moutline in AArch64 right now. If we're not compiling
- // for AArch64, emit a warning and ignore the flag. Otherwise, add the
- // proper mllvm flags.
- if (Triple.getArch() != llvm::Triple::aarch64 &&
- Triple.getArch() != llvm::Triple::aarch64_32) {
+ // 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)) {
D.Diag(diag::warn_drv_moutline_unsupported_opt) << Triple.getArchName();
} else {
CmdArgs.push_back("-mllvm");
@@ -6026,30 +6225,33 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
auto CLCommand =
getCLFallback()->GetCommand(C, JA, Output, Inputs, Args, LinkingOutput);
C.addCommand(std::make_unique<FallbackCommand>(
- JA, *this, Exec, CmdArgs, Inputs, std::move(CLCommand)));
+ JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs,
+ std::move(CLCommand)));
} else if (Args.hasArg(options::OPT__SLASH_fallback) &&
isa<PrecompileJobAction>(JA)) {
// In /fallback builds, run the main compilation even if the pch generation
// fails, so that the main compilation's fallback to cl.exe runs.
- C.addCommand(std::make_unique<ForceSuccessCommand>(JA, *this, Exec,
- CmdArgs, Inputs));
+ C.addCommand(std::make_unique<ForceSuccessCommand>(
+ JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs));
} else if (D.CC1Main && !D.CCGenDiagnostics) {
// Invoke the CC1 directly in this process
- C.addCommand(
- std::make_unique<CC1Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<CC1Command>(
+ JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs));
} else {
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs));
}
// Make the compile command echo its inputs for /showFilenames.
if (Output.getType() == types::TY_Object &&
Args.hasFlag(options::OPT__SLASH_showFilenames,
options::OPT__SLASH_showFilenames_, false)) {
- C.getJobs().getJobs().back()->setPrintInputFilenames(true);
+ C.getJobs().getJobs().back()->PrintInputFilenames = true;
}
if (Arg *A = Args.getLastArg(options::OPT_pg))
- if (FPKeepKind == CodeGenOptions::FramePointerKind::None)
+ if (FPKeepKind == CodeGenOptions::FramePointerKind::None &&
+ !Args.hasArg(options::OPT_mfentry))
D.Diag(diag::err_drv_argument_not_allowed_with) << "-fomit-frame-pointer"
<< A->getAsString(Args);
@@ -6072,7 +6274,7 @@ Clang::Clang(const ToolChain &TC)
// 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, RF_Full) {}
+ : Tool("clang", "clang frontend", TC) {}
Clang::~Clang() {}
@@ -6080,6 +6282,7 @@ Clang::~Clang() {}
///
/// Returns true if the runtime is non-fragile.
ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,
+ const InputInfoList &inputs,
ArgStringList &cmdArgs,
RewriteKind rewriteKind) const {
// Look for the controlling runtime option.
@@ -6203,8 +6406,11 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,
runtime = ObjCRuntime(ObjCRuntime::GCC, VersionTuple());
}
- cmdArgs.push_back(
- args.MakeArgString("-fobjc-runtime=" + runtime.getAsString()));
+ if (llvm::any_of(inputs, [](const InputInfo &input) {
+ return types::isObjC(input.getType());
+ }))
+ cmdArgs.push_back(
+ args.MakeArgString("-fobjc-runtime=" + runtime.getAsString()));
return runtime;
}
@@ -6274,6 +6480,7 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
codegenoptions::DebugInfoKind *DebugInfoKind,
bool *EmitCodeView) const {
unsigned RTOptionID = options::OPT__SLASH_MT;
+ bool isNVPTX = getToolChain().getTriple().isNVPTX();
if (Args.hasArg(options::OPT__SLASH_LDd))
// The /LDd option implies /MTd. The dependent lib part can be overridden,
@@ -6326,7 +6533,13 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
CmdArgs.push_back("--dependent-lib=oldnames");
}
- Args.AddLastArg(CmdArgs, options::OPT_show_includes);
+ if (Arg *ShowIncludes =
+ Args.getLastArg(options::OPT__SLASH_showIncludes,
+ options::OPT__SLASH_showIncludes_user)) {
+ CmdArgs.push_back("--show-includes");
+ if (ShowIncludes->getOption().matches(options::OPT__SLASH_showIncludes))
+ CmdArgs.push_back("-sys-header-deps");
+ }
// This controls whether or not we emit RTTI data for polymorphic types.
if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR,
@@ -6335,8 +6548,8 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
// This controls whether or not we emit stack-protector instrumentation.
// In MSVC, Buffer Security Check (/GS) is on by default.
- if (Args.hasFlag(options::OPT__SLASH_GS, options::OPT__SLASH_GS_,
- /*Default=*/true)) {
+ if (!isNVPTX && Args.hasFlag(options::OPT__SLASH_GS, options::OPT__SLASH_GS_,
+ /*Default=*/true)) {
CmdArgs.push_back("-stack-protector");
CmdArgs.push_back(Args.MakeArgString(Twine(LangOptions::SSPStrong)));
}
@@ -6347,7 +6560,7 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
options::OPT_gline_tables_only)) {
*EmitCodeView = true;
if (DebugInfoArg->getOption().matches(options::OPT__SLASH_Z7))
- *DebugInfoKind = codegenoptions::LimitedDebugInfo;
+ *DebugInfoKind = codegenoptions::DebugInfoConstructor;
else
*DebugInfoKind = codegenoptions::DebugLineTablesOnly;
} else {
@@ -6356,7 +6569,7 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
const Driver &D = getToolChain().getDriver();
EHFlags EH = parseClangCLEHFlags(D, Args);
- if (EH.Synch || EH.Asynch) {
+ if (!isNVPTX && (EH.Synch || EH.Asynch)) {
if (types::isCXX(InputType))
CmdArgs.push_back("-fcxx-exceptions");
CmdArgs.push_back("-fexceptions");
@@ -6425,7 +6638,7 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
options::OPT__SLASH_Gregcall)) {
unsigned DCCOptId = CCArg->getOption().getID();
const char *DCCFlag = nullptr;
- bool ArchSupported = true;
+ bool ArchSupported = !isNVPTX;
llvm::Triple::ArchType Arch = getToolChain().getArch();
switch (DCCOptId) {
case options::OPT__SLASH_Gd:
@@ -6531,7 +6744,8 @@ void ClangAs::AddMIPSTargetArgs(const ArgList &Args,
void ClangAs::AddX86TargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
- addX86AlignBranchArgs(getToolChain().getDriver(), Args, CmdArgs);
+ addX86AlignBranchArgs(getToolChain().getDriver(), Args, CmdArgs,
+ /*IsLTO=*/false);
if (Arg *A = Args.getLastArg(options::OPT_masm_EQ)) {
StringRef Value = A->getValue();
@@ -6601,7 +6815,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
}
// Add the target features
- getTargetFeatures(getToolChain(), Triple, Args, CmdArgs, true);
+ getTargetFeatures(D, Triple, Args, CmdArgs, true);
// Ignore explicit -force_cpusubtype_ALL option.
(void)Args.hasArg(options::OPT_force__cpusubtype__ALL);
@@ -6643,7 +6857,7 @@ 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::LimitedDebugInfo
+ DebugInfoKind = (WantDebug ? codegenoptions::DebugInfoConstructor
: codegenoptions::NoDebugInfo);
// Add the -fdebug-compilation-dir flag if needed.
addDebugCompDirArg(Args, CmdArgs, C.getDriver().getVFS());
@@ -6686,7 +6900,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
SmallString<256> Flags;
const char *Exec = getToolChain().getDriver().getClangProgramPath();
- Flags += Exec;
+ EscapeSpacesAndBackslashes(Exec, Flags);
for (const char *OriginalArg : OriginalArgs) {
SmallString<128> EscapedArg;
EscapeSpacesAndBackslashes(OriginalArg, EscapedArg);
@@ -6763,7 +6977,8 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Input.getFilename());
const char *Exec = getToolChain().getDriver().getClangProgramPath();
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs));
}
// Begin OffloadBundler
@@ -6847,7 +7062,7 @@ void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA,
// All the inputs are encoded as commands.
C.addCommand(std::make_unique<Command>(
- JA, *this,
+ JA, *this, ResponseFileSupport::None(),
TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())),
CmdArgs, None));
}
@@ -6913,7 +7128,7 @@ void OffloadBundler::ConstructJobMultipleOutputs(
// All the inputs are encoded as commands.
C.addCommand(std::make_unique<Command>(
- JA, *this,
+ JA, *this, ResponseFileSupport::None(),
TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())),
CmdArgs, None));
}
@@ -6943,7 +7158,7 @@ void OffloadWrapper::ConstructJob(Compilation &C, const JobAction &JA,
}
C.addCommand(std::make_unique<Command>(
- JA, *this,
+ JA, *this, ResponseFileSupport::None(),
Args.MakeArgString(getToolChain().GetProgramPath(getShortName())),
CmdArgs, Inputs));
}
diff --git a/clang/lib/Driver/ToolChains/Clang.h b/clang/lib/Driver/ToolChains/Clang.h
index b345c02489d4d..a607e3c27de9f 100644
--- a/clang/lib/Driver/ToolChains/Clang.h
+++ b/clang/lib/Driver/ToolChains/Clang.h
@@ -73,10 +73,13 @@ private:
llvm::opt::ArgStringList &CmdArgs) const;
void AddWebAssemblyTargetArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
+ void AddVETargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
enum RewriteKind { RK_None, RK_Fragile, RK_NonFragile };
ObjCRuntime AddObjCRuntimeArgs(const llvm::opt::ArgList &args,
+ const InputInfoList &inputs,
llvm::opt::ArgStringList &cmdArgs,
RewriteKind rewrite) const;
@@ -118,7 +121,7 @@ public:
class LLVM_LIBRARY_VISIBILITY ClangAs : public Tool {
public:
ClangAs(const ToolChain &TC)
- : Tool("clang::as", "clang integrated assembler", TC, RF_Full) {}
+ : Tool("clang::as", "clang integrated assembler", TC) {}
void AddMIPSTargetArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
void AddX86TargetArgs(const llvm::opt::ArgList &Args,
diff --git a/clang/lib/Driver/ToolChains/CloudABI.cpp b/clang/lib/Driver/ToolChains/CloudABI.cpp
index cf1d0d551e570..8dcfd4951bbfe 100644
--- a/clang/lib/Driver/ToolChains/CloudABI.cpp
+++ b/clang/lib/Driver/ToolChains/CloudABI.cpp
@@ -75,7 +75,7 @@ void cloudabi::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (D.isUsingLTO()) {
assert(!Inputs.empty() && "Must have at least one input.");
- AddGoldPlugin(ToolChain, Args, CmdArgs, Output, Inputs[0],
+ addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs[0],
D.getLTOMode() == LTOK_Thin);
}
@@ -92,7 +92,8 @@ void cloudabi::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
}
// CloudABI - CloudABI tool chain which can call ld(1) directly.
@@ -102,7 +103,7 @@ CloudABI::CloudABI(const Driver &D, const llvm::Triple &Triple,
: Generic_ELF(D, Triple, Args) {
SmallString<128> P(getDriver().Dir);
llvm::sys::path::append(P, "..", getTriple().str(), "lib");
- getFilePaths().push_back(P.str());
+ getFilePaths().push_back(std::string(P.str()));
}
void CloudABI::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
diff --git a/clang/lib/Driver/ToolChains/CloudABI.h b/clang/lib/Driver/ToolChains/CloudABI.h
index cc381c2b1e1fe..98bf23127706e 100644
--- a/clang/lib/Driver/ToolChains/CloudABI.h
+++ b/clang/lib/Driver/ToolChains/CloudABI.h
@@ -19,9 +19,9 @@ namespace tools {
/// cloudabi -- Directly call GNU Binutils linker
namespace cloudabi {
-class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
- Linker(const ToolChain &TC) : GnuTool("cloudabi::Linker", "linker", TC) {}
+ Linker(const ToolChain &TC) : Tool("cloudabi::Linker", "linker", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 37ec734685706..1cac5a0822a4b 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -12,6 +12,7 @@
#include "Arch/Mips.h"
#include "Arch/PPC.h"
#include "Arch/SystemZ.h"
+#include "Arch/VE.h"
#include "Arch/X86.h"
#include "HIP.h"
#include "Hexagon.h"
@@ -50,6 +51,7 @@
#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"
@@ -82,6 +84,31 @@ void tools::handleTargetFeaturesGroup(const ArgList &Args,
}
}
+std::vector<StringRef>
+tools::unifyTargetFeatures(const std::vector<StringRef> &Features) {
+ std::vector<StringRef> UnifiedFeatures;
+ // Find the last of each feature.
+ llvm::StringMap<unsigned> LastOpt;
+ for (unsigned I = 0, N = Features.size(); I < N; ++I) {
+ StringRef Name = Features[I];
+ assert(Name[0] == '-' || Name[0] == '+');
+ LastOpt[Name.drop_front(1)] = I;
+ }
+
+ 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;
+}
+
void tools::addDirectoryList(const ArgList &Args, ArgStringList &CmdArgs,
const char *ArgName, const char *EnvVar) {
const char *DirList = ::getenv(EnvVar);
@@ -91,7 +118,7 @@ void tools::addDirectoryList(const ArgList &Args, ArgStringList &CmdArgs,
return; // Nothing to do.
StringRef Name(ArgName);
- if (Name.equals("-I") || Name.equals("-L"))
+ if (Name.equals("-I") || Name.equals("-L") || Name.empty())
CombinedArg = true;
StringRef Dirs(DirList);
@@ -151,14 +178,12 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs,
addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH");
for (const auto &II : Inputs) {
- // If the current tool chain refers to an OpenMP or HIP offloading host, we
- // should ignore inputs that refer to OpenMP or HIP offloading devices -
+ // If the current tool chain refers to an OpenMP offloading host, we
+ // should ignore inputs that refer to OpenMP offloading devices -
// they will be embedded according to a proper linker script.
if (auto *IA = II.getAction())
if ((JA.isHostOffloading(Action::OFK_OpenMP) &&
- IA->isDeviceOffloading(Action::OFK_OpenMP)) ||
- (JA.isHostOffloading(Action::OFK_HIP) &&
- IA->isDeviceOffloading(Action::OFK_HIP)))
+ IA->isDeviceOffloading(Action::OFK_OpenMP)))
continue;
if (!TC.HasNativeLLVMSupport() && types::isLLVMIR(II.getType()))
@@ -278,7 +303,7 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T,
StringRef CPUName;
StringRef ABIName;
mips::getMipsCPUAndABI(Args, T, CPUName, ABIName);
- return CPUName;
+ return std::string(CPUName);
}
case llvm::Triple::nvptx:
@@ -293,15 +318,19 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T,
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 Darwin)
- if (TargetCPUName.empty() && !T.isOSDarwin()) {
- if (T.getArch() == llvm::Triple::ppc64)
- TargetCPUName = "ppc64";
- else if (T.getArch() == llvm::Triple::ppc64le)
- TargetCPUName = "ppc64le";
- else
- TargetCPUName = "ppc";
- }
+ // each architecture. (except on AIX)
+ if (!TargetCPUName.empty())
+ return TargetCPUName;
+
+ if (T.isOSAIX())
+ TargetCPUName = "pwr4";
+ else if (T.getArch() == llvm::Triple::ppc64le)
+ TargetCPUName = "ppc64le";
+ else if (T.getArch() == llvm::Triple::ppc64)
+ TargetCPUName = "ppc64";
+ else
+ TargetCPUName = "ppc";
+
return TargetCPUName;
}
@@ -334,18 +363,18 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T,
case llvm::Triple::wasm32:
case llvm::Triple::wasm64:
- return getWebAssemblyTargetCPU(Args);
+ return std::string(getWebAssemblyTargetCPU(Args));
}
}
-unsigned tools::getLTOParallelism(const ArgList &Args, const Driver &D) {
- unsigned Parallelism = 0;
+llvm::StringRef tools::getLTOParallelism(const ArgList &Args, const Driver &D) {
Arg *LtoJobsArg = Args.getLastArg(options::OPT_flto_jobs_EQ);
- if (LtoJobsArg &&
- StringRef(LtoJobsArg->getValue()).getAsInteger(10, Parallelism))
- D.Diag(diag::err_drv_invalid_int_value) << LtoJobsArg->getAsString(Args)
- << LtoJobsArg->getValue();
- return Parallelism;
+ if (!LtoJobsArg)
+ return {};
+ if (!llvm::get_threadpool_strategy(LtoJobsArg->getValue()))
+ D.Diag(diag::err_drv_invalid_int_value)
+ << LtoJobsArg->getAsString(Args) << LtoJobsArg->getValue();
+ return LtoJobsArg->getValue();
}
// CloudABI uses -ffunction-sections and -fdata-sections by default.
@@ -353,28 +382,32 @@ bool tools::isUseSeparateSections(const llvm::Triple &Triple) {
return Triple.getOS() == llvm::Triple::CloudABI;
}
-void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
+void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,
ArgStringList &CmdArgs, const InputInfo &Output,
const InputInfo &Input, bool IsThinLTO) {
- // 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");
+ const char *Linker = Args.MakeArgString(ToolChain.GetLinkerPath());
+ const Driver &D = ToolChain.getDriver();
+ if (llvm::sys::path::filename(Linker) != "ld.lld" &&
+ llvm::sys::path::stem(Linker) != "ld.lld") {
+ // 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");
#if defined(_WIN32)
- const char *Suffix = ".dll";
+ const char *Suffix = ".dll";
#elif defined(__APPLE__)
- const char *Suffix = ".dylib";
+ const char *Suffix = ".dylib";
#else
- const char *Suffix = ".so";
+ const char *Suffix = ".so";
#endif
- SmallString<1024> Plugin;
- llvm::sys::path::native(Twine(ToolChain.getDriver().Dir) +
- "/../lib" CLANG_LIBDIR_SUFFIX "/LLVMgold" +
- Suffix,
- Plugin);
- CmdArgs.push_back(Args.MakeArgString(Plugin));
+ SmallString<1024> Plugin;
+ llvm::sys::path::native(
+ Twine(D.Dir) + "/../lib" CLANG_LIBDIR_SUFFIX "/LLVMgold" + Suffix,
+ Plugin);
+ CmdArgs.push_back(Args.MakeArgString(Plugin));
+ }
// Try to pass driver level flags relevant to LTO code generation down to
// the plugin.
@@ -385,13 +418,19 @@ void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=mcpu=") + CPU));
if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
+ // The optimization level matches
+ // CompilerInvocation.cpp:getOptimizationLevel().
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))
+ else if (A->getOption().matches(options::OPT_O)) {
OOpt = A->getValue();
- else if (A->getOption().matches(options::OPT_O0))
+ 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("-plugin-opt=O") + OOpt));
@@ -406,7 +445,8 @@ void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
if (IsThinLTO)
CmdArgs.push_back("-plugin-opt=thinlto");
- if (unsigned Parallelism = getLTOParallelism(Args, ToolChain.getDriver()))
+ StringRef Parallelism = getLTOParallelism(Args, D);
+ if (!Parallelism.empty())
CmdArgs.push_back(
Args.MakeArgString("-plugin-opt=jobs=" + Twine(Parallelism)));
@@ -437,7 +477,7 @@ void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
if (Arg *A = getLastProfileSampleUseArg(Args)) {
StringRef FName = A->getValue();
if (!llvm::sys::fs::exists(FName))
- ToolChain.getDriver().Diag(diag::err_drv_no_such_file) << FName;
+ D.Diag(diag::err_drv_no_such_file) << FName;
else
CmdArgs.push_back(
Args.MakeArgString(Twine("-plugin-opt=sample-profile=") + FName));
@@ -480,17 +520,21 @@ void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
}
// Setup statistics file output.
- SmallString<128> StatsFile =
- getStatsFileName(Args, Output, Input, ToolChain.getDriver());
+ SmallString<128> StatsFile = getStatsFileName(Args, Output, Input, D);
if (!StatsFile.empty())
CmdArgs.push_back(
Args.MakeArgString(Twine("-plugin-opt=stats-file=") + StatsFile));
+
+ addX86AlignBranchArgs(D, Args, CmdArgs, /*IsLTO=*/true);
}
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, false))
+ options::OPT_fno_rtlib_add_rpath, DefaultValue))
return;
std::string CandidateRPath = TC.getArchSpecificLibPath();
@@ -583,6 +627,11 @@ static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args,
void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
ArgStringList &CmdArgs) {
+ // Fuchsia never needs these. Any sanitizer runtimes with system
+ // dependencies use the `.deplibs` feature instead.
+ if (TC.getTriple().isOSFuchsia())
+ return;
+
// Force linking against the system libraries sanitizers depends on
// (see PR15823 why this is necessary).
CmdArgs.push_back("--no-as-needed");
@@ -642,17 +691,21 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
StaticRuntimes.push_back("stats_client");
// Collect static runtimes.
- if (Args.hasArg(options::OPT_shared) || SanArgs.needsSharedRt()) {
- // Don't link static runtimes into DSOs or if -shared-libasan.
+ if (Args.hasArg(options::OPT_shared)) {
+ // Don't link static runtimes into DSOs.
return;
}
- if (SanArgs.needsAsanRt() && SanArgs.linkRuntimes()) {
+
+ // 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()) {
StaticRuntimes.push_back("asan");
if (SanArgs.linkCXXRuntimes())
StaticRuntimes.push_back("asan_cxx");
}
- if (SanArgs.needsHwasanRt() && SanArgs.linkRuntimes()) {
+ if (!SanArgs.needsSharedRt() && SanArgs.needsHwasanRt() && SanArgs.linkRuntimes()) {
StaticRuntimes.push_back("hwasan");
if (SanArgs.linkCXXRuntimes())
StaticRuntimes.push_back("hwasan_cxx");
@@ -671,7 +724,7 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
if (SanArgs.linkCXXRuntimes())
StaticRuntimes.push_back("tsan_cxx");
}
- if (SanArgs.needsUbsanRt() && SanArgs.linkRuntimes()) {
+ if (!SanArgs.needsSharedRt() && SanArgs.needsUbsanRt() && SanArgs.linkRuntimes()) {
if (SanArgs.requiresMinimalRuntime()) {
StaticRuntimes.push_back("ubsan_minimal");
} else {
@@ -684,18 +737,20 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
NonWholeStaticRuntimes.push_back("safestack");
RequiredSymbols.push_back("__safestack_init");
}
- if (SanArgs.needsCfiRt() && SanArgs.linkRuntimes())
- StaticRuntimes.push_back("cfi");
- if (SanArgs.needsCfiDiagRt() && SanArgs.linkRuntimes()) {
- StaticRuntimes.push_back("cfi_diag");
- if (SanArgs.linkCXXRuntimes())
- StaticRuntimes.push_back("ubsan_standalone_cxx");
+ if (!(SanArgs.needsSharedRt() && SanArgs.needsUbsanRt() && SanArgs.linkRuntimes())) {
+ if (SanArgs.needsCfiRt() && SanArgs.linkRuntimes())
+ StaticRuntimes.push_back("cfi");
+ if (SanArgs.needsCfiDiagRt() && SanArgs.linkRuntimes()) {
+ StaticRuntimes.push_back("cfi_diag");
+ if (SanArgs.linkCXXRuntimes())
+ StaticRuntimes.push_back("ubsan_standalone_cxx");
+ }
}
if (SanArgs.needsStatsRt() && SanArgs.linkRuntimes()) {
NonWholeStaticRuntimes.push_back("stats");
RequiredSymbols.push_back("__sanitizer_stats_register");
}
- if (SanArgs.needsScudoRt() && SanArgs.linkRuntimes()) {
+ if (!SanArgs.needsSharedRt() && SanArgs.needsScudoRt() && SanArgs.linkRuntimes()) {
if (SanArgs.requiresMinimalRuntime()) {
StaticRuntimes.push_back("scudo_minimal");
if (SanArgs.linkCXXRuntimes())
@@ -751,7 +806,7 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
CmdArgs.push_back("--export-dynamic");
if (SanArgs.hasCrossDsoCfi() && !AddExportDynamic)
- CmdArgs.push_back("-export-dynamic-symbol=__cfi_check");
+ CmdArgs.push_back("--export-dynamic-symbol=__cfi_check");
return !StaticRuntimes.empty() || !NonWholeStaticRuntimes.empty();
}
@@ -834,10 +889,12 @@ void tools::SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T,
InputInfo II(types::TY_Object, Output.getFilename(), Output.getFilename());
// First extract the dwo sections.
- C.addCommand(std::make_unique<Command>(JA, T, Exec, ExtractArgs, II));
+ C.addCommand(std::make_unique<Command>(
+ JA, T, ResponseFileSupport::AtFileCurCP(), Exec, ExtractArgs, II));
// Then remove them from the original .o file.
- C.addCommand(std::make_unique<Command>(JA, T, Exec, StripArgs, II));
+ C.addCommand(std::make_unique<Command>(
+ JA, T, ResponseFileSupport::AtFileCurCP(), Exec, StripArgs, II));
}
// Claim options we don't want to warn if they are unused. We do this for
@@ -1211,7 +1268,14 @@ static void AddUnwindLibrary(const ToolChain &TC, const Driver &D,
case ToolChain::UNW_CompilerRT:
if (LGT == LibGccType::StaticLibGcc)
CmdArgs.push_back("-l:libunwind.a");
- else
+ else if (TC.getTriple().isOSCygMing()) {
+ if (LGT == LibGccType::SharedLibGcc)
+ 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");
+ } else
CmdArgs.push_back("-l:libunwind.so");
break;
}
@@ -1263,114 +1327,6 @@ void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D,
}
}
-/// Add HIP linker script arguments at the end of the argument list so that
-/// the fat binary is built by embedding the device images into the host. The
-/// linker script also defines a symbol required by the code generation so that
-/// the image can be retrieved at runtime. This should be used only in tool
-/// chains that support linker scripts.
-void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C,
- const InputInfo &Output,
- const InputInfoList &Inputs, const ArgList &Args,
- ArgStringList &CmdArgs, const JobAction &JA,
- const Tool &T) {
-
- // If this is not a HIP host toolchain, we don't need to do anything.
- if (!JA.isHostOffloading(Action::OFK_HIP))
- return;
-
- InputInfoList DeviceInputs;
- for (const auto &II : Inputs) {
- const Action *A = II.getAction();
- // Is this a device linking action?
- if (A && isa<LinkJobAction>(A) && A->isDeviceOffloading(Action::OFK_HIP)) {
- DeviceInputs.push_back(II);
- }
- }
-
- if (DeviceInputs.empty())
- return;
-
- // Create temporary linker script. Keep it if save-temps is enabled.
- const char *LKS;
- std::string Name = llvm::sys::path::filename(Output.getFilename());
- if (C.getDriver().isSaveTempsEnabled()) {
- LKS = C.getArgs().MakeArgString(Name + ".lk");
- } else {
- auto TmpName = C.getDriver().GetTemporaryPath(Name, "lk");
- LKS = C.addTempFile(C.getArgs().MakeArgString(TmpName));
- }
-
- // Add linker script option to the command.
- CmdArgs.push_back("-T");
- CmdArgs.push_back(LKS);
-
- // Create a buffer to write the contents of the linker script.
- std::string LksBuffer;
- llvm::raw_string_ostream LksStream(LksBuffer);
-
- // Get the HIP offload tool chain.
- auto *HIPTC = static_cast<const toolchains::CudaToolChain *>(
- C.getSingleOffloadToolChain<Action::OFK_HIP>());
- assert(HIPTC->getTriple().getArch() == llvm::Triple::amdgcn &&
- "Wrong platform");
- (void)HIPTC;
-
- const char *BundleFile;
- if (C.getDriver().isSaveTempsEnabled()) {
- BundleFile = C.getArgs().MakeArgString(Name + ".hipfb");
- } else {
- auto TmpName = C.getDriver().GetTemporaryPath(Name, "hipfb");
- BundleFile = C.addTempFile(C.getArgs().MakeArgString(TmpName));
- }
- AMDGCN::constructHIPFatbinCommand(C, JA, BundleFile, DeviceInputs, Args, T);
-
- // Add commands 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.
- LksStream << "/*\n";
- LksStream << " HIP Offload Linker Script\n";
- LksStream << " *** Automatically generated by Clang ***\n";
- LksStream << "*/\n";
- LksStream << "TARGET(binary)\n";
- LksStream << "INPUT(" << BundleFile << ")\n";
- LksStream << "SECTIONS\n";
- LksStream << "{\n";
- LksStream << " .hip_fatbin :\n";
- LksStream << " ALIGN(0x10)\n";
- LksStream << " {\n";
- LksStream << " PROVIDE_HIDDEN(__hip_fatbin = .);\n";
- LksStream << " " << BundleFile << "\n";
- LksStream << " }\n";
- LksStream << " /DISCARD/ :\n";
- LksStream << " {\n";
- LksStream << " * ( __CLANG_OFFLOAD_BUNDLE__* )\n";
- LksStream << " }\n";
- LksStream << "}\n";
- LksStream << "INSERT BEFORE .data\n";
- LksStream.flush();
-
- // Dump the contents of the linker script 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() << LksBuffer;
-
- // If this is a dry run, do not create the linker script file.
- if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH))
- return;
-
- // Open script file and write the contents.
- std::error_code EC;
- llvm::raw_fd_ostream Lksf(LKS, EC, llvm::sys::fs::OF_None);
-
- if (EC) {
- C.getDriver().Diag(clang::diag::err_unable_to_make_temp) << EC.message();
- return;
- }
-
- Lksf << LksBuffer;
-}
-
SmallString<128> tools::getStatsFileName(const llvm::opt::ArgList &Args,
const InputInfo &Output,
const InputInfo &Input,
@@ -1399,3 +1355,53 @@ void tools::addMultilibFlag(bool Enabled, const char *const Flag,
Multilib::flags_list &Flags) {
Flags.push_back(std::string(Enabled ? "+" : "-") + Flag);
}
+
+void tools::addX86AlignBranchArgs(const Driver &D, const ArgList &Args,
+ ArgStringList &CmdArgs, bool IsLTO) {
+ auto addArg = [&, IsLTO](const Twine &Arg) {
+ if (IsLTO) {
+ CmdArgs.push_back(Args.MakeArgString("-plugin-opt=" + Arg));
+ } else {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back(Args.MakeArgString(Arg));
+ }
+ };
+
+ if (Args.hasArg(options::OPT_mbranches_within_32B_boundaries)) {
+ addArg(Twine("-x86-branches-within-32B-boundaries"));
+ }
+ if (const Arg *A = Args.getLastArg(options::OPT_malign_branch_boundary_EQ)) {
+ StringRef Value = A->getValue();
+ unsigned Boundary;
+ if (Value.getAsInteger(10, Boundary) || Boundary < 16 ||
+ !llvm::isPowerOf2_64(Boundary)) {
+ D.Diag(diag::err_drv_invalid_argument_to_option)
+ << Value << A->getOption().getName();
+ } else {
+ addArg("-x86-align-branch-boundary=" + Twine(Boundary));
+ }
+ }
+ if (const Arg *A = Args.getLastArg(options::OPT_malign_branch_EQ)) {
+ std::string AlignBranch;
+ for (StringRef T : A->getValues()) {
+ if (T != "fused" && T != "jcc" && T != "jmp" && T != "call" &&
+ T != "ret" && T != "indirect")
+ D.Diag(diag::err_drv_invalid_malign_branch_EQ)
+ << T << "fused, jcc, jmp, call, ret, indirect";
+ if (!AlignBranch.empty())
+ AlignBranch += '+';
+ AlignBranch += T;
+ }
+ addArg("-x86-align-branch=" + Twine(AlignBranch));
+ }
+ if (const Arg *A = Args.getLastArg(options::OPT_mpad_max_prefix_size_EQ)) {
+ StringRef Value = A->getValue();
+ unsigned PrefixSize;
+ if (Value.getAsInteger(10, PrefixSize)) {
+ D.Diag(diag::err_drv_invalid_argument_to_option)
+ << Value << A->getOption().getName();
+ } else {
+ addArg("-x86-pad-max-prefix-size=" + Twine(PrefixSize));
+ }
+ }
+}
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h
index 84b9d2cf59b49..29dedec9b09cd 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.h
+++ b/clang/lib/Driver/ToolChains/CommonArgs.h
@@ -45,12 +45,6 @@ void AddRunTimeLibs(const ToolChain &TC, const Driver &D,
llvm::opt::ArgStringList &CmdArgs,
const llvm::opt::ArgList &Args);
-void AddHIPLinkerScript(const ToolChain &TC, Compilation &C,
- const InputInfo &Output, const InputInfoList &Inputs,
- const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs, const JobAction &JA,
- const Tool &T);
-
const char *SplitDebugName(const llvm::opt::ArgList &Args,
const InputInfo &Input, const InputInfo &Output);
@@ -58,7 +52,7 @@ void SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T,
const JobAction &JA, const llvm::opt::ArgList &Args,
const InputInfo &Output, const char *OutFile);
-void AddGoldPlugin(const ToolChain &ToolChain, const llvm::opt::ArgList &Args,
+void addLTOOptions(const ToolChain &ToolChain, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs, const InputInfo &Output,
const InputInfo &Input, bool IsThinLTO);
@@ -88,12 +82,18 @@ llvm::opt::Arg *getLastProfileSampleUseArg(const llvm::opt::ArgList &Args);
bool isObjCAutoRefCount(const llvm::opt::ArgList &Args);
-unsigned getLTOParallelism(const llvm::opt::ArgList &Args, const Driver &D);
+llvm::StringRef getLTOParallelism(const llvm::opt::ArgList &Args,
+ const Driver &D);
bool areOptimizationsEnabled(const llvm::opt::ArgList &Args);
bool isUseSeparateSections(const llvm::Triple &Triple);
+/// \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
+/// is prefixed by \p ArgName then added to \p Args. Otherwise, for each
+/// entry of \p EnvVar, \p ArgName is added to \p Args first, then the entry
+/// itself is added.
void addDirectoryList(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs, const char *ArgName,
const char *EnvVar);
@@ -106,10 +106,20 @@ void AddTargetFeature(const llvm::opt::ArgList &Args,
std::string getCPUName(const llvm::opt::ArgList &Args, const llvm::Triple &T,
bool FromAs = false);
+/// Iterate \p Args and convert -mxxx to +xxx and -mno-xxx to -xxx and
+/// append it to \p Features.
+///
+/// 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,
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);
+
/// Handles the -save-stats option and returns the filename to save statistics
/// to.
SmallString<128> getStatsFileName(const llvm::opt::ArgList &Args,
@@ -121,6 +131,8 @@ SmallString<128> getStatsFileName(const llvm::opt::ArgList &Args,
void addMultilibFlag(bool Enabled, const char *const Flag,
Multilib::flags_list &Flags);
+void addX86AlignBranchArgs(const Driver &D, const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs, bool IsLTO);
} // end namespace tools
} // end namespace driver
} // end namespace clang
diff --git a/clang/lib/Driver/ToolChains/CrossWindows.cpp b/clang/lib/Driver/ToolChains/CrossWindows.cpp
index dbf6114eb2ecc..127a8a5f24cce 100644
--- a/clang/lib/Driver/ToolChains/CrossWindows.cpp
+++ b/clang/lib/Driver/ToolChains/CrossWindows.cpp
@@ -57,7 +57,8 @@ void tools::CrossWindows::Assembler::ConstructJob(
const std::string Assembler = TC.GetProgramPath("as");
Exec = Args.MakeArgString(Assembler);
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Exec, CmdArgs, Inputs));
}
void tools::CrossWindows::Linker::ConstructJob(
@@ -202,7 +203,8 @@ void tools::CrossWindows::Linker::ConstructJob(
Exec = Args.MakeArgString(TC.GetLinkerPath());
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs));
}
CrossWindowsToolChain::CrossWindowsToolChain(const Driver &D,
diff --git a/clang/lib/Driver/ToolChains/CrossWindows.h b/clang/lib/Driver/ToolChains/CrossWindows.h
index 7267a35d48b94..df9a7f71bf9ff 100644
--- a/clang/lib/Driver/ToolChains/CrossWindows.h
+++ b/clang/lib/Driver/ToolChains/CrossWindows.h
@@ -33,8 +33,7 @@ public:
class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
- Linker(const ToolChain &TC)
- : Tool("CrossWindows::Linker", "ld", TC, RF_Full) {}
+ Linker(const ToolChain &TC) : Tool("CrossWindows::Linker", "ld", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp
index 02871d2ce411f..110a0bca9bc18 100644
--- a/clang/lib/Driver/ToolChains/Cuda.cpp
+++ b/clang/lib/Driver/ToolChains/Cuda.cpp
@@ -18,9 +18,11 @@
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.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/TargetParser.h"
#include "llvm/Support/VirtualFileSystem.h"
#include <system_error>
@@ -32,37 +34,33 @@ using namespace llvm::opt;
// 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".
-static CudaVersion ParseCudaVersionFile(llvm::StringRef V) {
+void CudaInstallationDetector::ParseCudaVersionFile(llvm::StringRef V) {
+ Version = CudaVersion::UNKNOWN;
if (!V.startswith("CUDA Version "))
- return CudaVersion::UNKNOWN;
+ return;
V = V.substr(strlen("CUDA Version "));
- int Major = -1, Minor = -1;
- auto First = V.split('.');
- auto Second = First.second.split('.');
- if (First.first.getAsInteger(10, Major) ||
- Second.first.getAsInteger(10, Minor))
- return CudaVersion::UNKNOWN;
-
- if (Major == 7 && Minor == 0) {
- // This doesn't appear to ever happen -- version.txt doesn't exist in the
- // CUDA 7 installs I've seen. But no harm in checking.
- return CudaVersion::CUDA_70;
+ SmallVector<StringRef,4> VersionParts;
+ V.split(VersionParts, '.');
+ if (VersionParts.size() < 2)
+ return;
+ DetectedVersion = join_items(".", VersionParts[0], VersionParts[1]);
+ Version = CudaStringToVersion(DetectedVersion);
+ if (Version != CudaVersion::UNKNOWN) {
+ // TODO(tra): remove the warning once we have all features of 10.2 and 11.0
+ // implemented.
+ DetectedVersionIsNotSupported = Version > CudaVersion::LATEST_SUPPORTED;
+ return;
}
- if (Major == 7 && Minor == 5)
- return CudaVersion::CUDA_75;
- if (Major == 8 && Minor == 0)
- return CudaVersion::CUDA_80;
- if (Major == 9 && Minor == 0)
- return CudaVersion::CUDA_90;
- if (Major == 9 && Minor == 1)
- return CudaVersion::CUDA_91;
- if (Major == 9 && Minor == 2)
- return CudaVersion::CUDA_92;
- if (Major == 10 && Minor == 0)
- return CudaVersion::CUDA_100;
- if (Major == 10 && Minor == 1)
- return CudaVersion::CUDA_101;
- return CudaVersion::UNKNOWN;
+
+ Version = CudaVersion::LATEST_SUPPORTED;
+ DetectedVersionIsNotSupported = true;
+}
+
+void CudaInstallationDetector::WarnIfUnsupportedVersion() {
+ if (DetectedVersionIsNotSupported)
+ D.Diag(diag::warn_drv_unknown_cuda_version)
+ << DetectedVersion
+ << CudaVersionToString(CudaVersion::LATEST_SUPPORTED);
}
CudaInstallationDetector::CudaInstallationDetector(
@@ -80,6 +78,7 @@ CudaInstallationDetector::CudaInstallationDetector(
// In decreasing order so we prefer newer versions to older versions.
std::initializer_list<const char *> Versions = {"8.0", "7.5", "7.0"};
+ auto &FS = D.getVFS();
if (Args.hasArg(clang::driver::options::OPT_cuda_path_EQ)) {
Candidates.emplace_back(
@@ -106,8 +105,9 @@ CudaInstallationDetector::CudaInstallationDetector(
StringRef ptxasDir = llvm::sys::path::parent_path(ptxasAbsolutePath);
if (llvm::sys::path::filename(ptxasDir) == "bin")
- Candidates.emplace_back(llvm::sys::path::parent_path(ptxasDir),
- /*StrictChecking=*/true);
+ Candidates.emplace_back(
+ std::string(llvm::sys::path::parent_path(ptxasDir)),
+ /*StrictChecking=*/true);
}
}
@@ -115,7 +115,7 @@ CudaInstallationDetector::CudaInstallationDetector(
for (const char *Ver : Versions)
Candidates.emplace_back(D.SysRoot + "/usr/local/cuda-" + Ver);
- Distro Dist(D.getVFS(), llvm::Triple(llvm::sys::getProcessTriple()));
+ Distro Dist(FS, llvm::Triple(llvm::sys::getProcessTriple()));
if (Dist.IsDebian() || Dist.IsUbuntu())
// Special case for Debian to have nvidia-cuda-toolkit work
// out of the box. More info on http://bugs.debian.org/882505
@@ -126,14 +126,13 @@ CudaInstallationDetector::CudaInstallationDetector(
for (const auto &Candidate : Candidates) {
InstallPath = Candidate.Path;
- if (InstallPath.empty() || !D.getVFS().exists(InstallPath))
+ if (InstallPath.empty() || !FS.exists(InstallPath))
continue;
BinPath = InstallPath + "/bin";
IncludePath = InstallPath + "/include";
LibDevicePath = InstallPath + "/nvvm/libdevice";
- auto &FS = D.getVFS();
if (!(FS.exists(IncludePath) && FS.exists(BinPath)))
continue;
bool CheckLibDevice = (!NoCudaLib || Candidate.StrictChecking);
@@ -160,25 +159,26 @@ CudaInstallationDetector::CudaInstallationDetector(
// version.txt isn't present.
Version = CudaVersion::CUDA_70;
} else {
- Version = ParseCudaVersionFile((*VersionFile)->getBuffer());
+ ParseCudaVersionFile((*VersionFile)->getBuffer());
}
if (Version >= CudaVersion::CUDA_90) {
// CUDA-9+ uses single libdevice file for all GPU variants.
std::string FilePath = LibDevicePath + "/libdevice.10.bc";
if (FS.exists(FilePath)) {
- for (const char *GpuArchName :
- {"sm_30", "sm_32", "sm_35", "sm_37", "sm_50", "sm_52", "sm_53",
- "sm_60", "sm_61", "sm_62", "sm_70", "sm_72", "sm_75"}) {
- const CudaArch GpuArch = StringToCudaArch(GpuArchName);
- if (Version >= MinVersionForCudaArch(GpuArch) &&
- Version <= MaxVersionForCudaArch(GpuArch))
- LibDeviceMap[GpuArchName] = FilePath;
+ for (int Arch = (int)CudaArch::SM_30, E = (int)CudaArch::LAST; Arch < E;
+ ++Arch) {
+ CudaArch GpuArch = static_cast<CudaArch>(Arch);
+ if (!IsNVIDIAGpuArch(GpuArch))
+ continue;
+ std::string GpuArchName(CudaArchToString(GpuArch));
+ LibDeviceMap[GpuArchName] = FilePath;
}
}
} else {
std::error_code EC;
- for (llvm::sys::fs::directory_iterator LI(LibDevicePath, EC), LE;
+ for (llvm::vfs::directory_iterator LI = FS.dir_begin(LibDevicePath, EC),
+ LE;
!EC && LI != LE; LI = LI.increment(EC)) {
StringRef FilePath = LI->path();
StringRef FileName = llvm::sys::path::filename(FilePath);
@@ -194,27 +194,27 @@ CudaInstallationDetector::CudaInstallationDetector(
// capability. NVCC's choice of the libdevice library version is
// rather peculiar and depends on the CUDA version.
if (GpuArch == "compute_20") {
- LibDeviceMap["sm_20"] = FilePath;
- LibDeviceMap["sm_21"] = FilePath;
- LibDeviceMap["sm_32"] = FilePath;
+ LibDeviceMap["sm_20"] = std::string(FilePath);
+ LibDeviceMap["sm_21"] = std::string(FilePath);
+ LibDeviceMap["sm_32"] = std::string(FilePath);
} else if (GpuArch == "compute_30") {
- LibDeviceMap["sm_30"] = FilePath;
+ LibDeviceMap["sm_30"] = std::string(FilePath);
if (Version < CudaVersion::CUDA_80) {
- LibDeviceMap["sm_50"] = FilePath;
- LibDeviceMap["sm_52"] = FilePath;
- LibDeviceMap["sm_53"] = FilePath;
+ LibDeviceMap["sm_50"] = std::string(FilePath);
+ LibDeviceMap["sm_52"] = std::string(FilePath);
+ LibDeviceMap["sm_53"] = std::string(FilePath);
}
- LibDeviceMap["sm_60"] = FilePath;
- LibDeviceMap["sm_61"] = FilePath;
- LibDeviceMap["sm_62"] = FilePath;
+ LibDeviceMap["sm_60"] = std::string(FilePath);
+ LibDeviceMap["sm_61"] = std::string(FilePath);
+ LibDeviceMap["sm_62"] = std::string(FilePath);
} else if (GpuArch == "compute_35") {
- LibDeviceMap["sm_35"] = FilePath;
- LibDeviceMap["sm_37"] = FilePath;
+ LibDeviceMap["sm_35"] = std::string(FilePath);
+ LibDeviceMap["sm_37"] = std::string(FilePath);
} else if (GpuArch == "compute_50") {
if (Version >= CudaVersion::CUDA_80) {
- LibDeviceMap["sm_50"] = FilePath;
- LibDeviceMap["sm_52"] = FilePath;
- LibDeviceMap["sm_53"] = FilePath;
+ LibDeviceMap["sm_50"] = std::string(FilePath);
+ LibDeviceMap["sm_52"] = std::string(FilePath);
+ LibDeviceMap["sm_53"] = std::string(FilePath);
}
}
}
@@ -242,7 +242,7 @@ void CudaInstallationDetector::AddCudaIncludeArgs(
CC1Args.push_back(DriverArgs.MakeArgString(P));
}
- if (DriverArgs.hasArg(options::OPT_nocudainc))
+ if (DriverArgs.hasArg(options::OPT_nogpuinc))
return;
if (!isValid()) {
@@ -423,7 +423,11 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
Exec = A->getValue();
else
Exec = Args.MakeArgString(TC.GetProgramPath("ptxas"));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this,
+ ResponseFileSupport{ResponseFileSupport::RF_Full, llvm::sys::WEM_UTF8,
+ "--options-file"},
+ Exec, CmdArgs, Inputs));
}
static bool shouldIncludePTX(const ArgList &Args, const char *gpu_arch) {
@@ -477,10 +481,9 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA,
continue;
// We need to pass an Arch of the form "sm_XX" for cubin files and
// "compute_XX" for ptx.
- const char *Arch =
- (II.getType() == types::TY_PP_Asm)
- ? CudaVirtualArchToString(VirtualArchForCudaArch(gpu_arch))
- : gpu_arch_str;
+ 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()));
}
@@ -489,7 +492,11 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(A));
const char *Exec = Args.MakeArgString(TC.GetProgramPath("fatbinary"));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this,
+ ResponseFileSupport{ResponseFileSupport::RF_Full, llvm::sys::WEM_UTF8,
+ "--options-file"},
+ Exec, CmdArgs, Inputs));
}
void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -566,7 +573,11 @@ void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("nvlink"));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this,
+ ResponseFileSupport{ResponseFileSupport::RF_Full, llvm::sys::WEM_UTF8,
+ "--options-file"},
+ Exec, CmdArgs, Inputs));
}
/// CUDA toolchain. Our assembler is ptxas, and our "linker" is fatbinary,
@@ -578,8 +589,10 @@ CudaToolChain::CudaToolChain(const Driver &D, const llvm::Triple &Triple,
const Action::OffloadKind OK)
: ToolChain(D, Triple, Args), HostTC(HostTC),
CudaInstallation(D, HostTC.getTriple(), Args), OK(OK) {
- if (CudaInstallation.isValid())
- getProgramPaths().push_back(CudaInstallation.getBinPath());
+ if (CudaInstallation.isValid()) {
+ CudaInstallation.WarnIfUnsupportedVersion();
+ getProgramPaths().push_back(std::string(CudaInstallation.getBinPath()));
+ }
// Lookup binaries into the driver directory, this is used to
// discover the clang-offload-bundler executable.
getProgramPaths().push_back(getDriver().Dir);
@@ -596,7 +609,7 @@ std::string CudaToolChain::getInputFilename(const InputInfo &Input) const {
// these particular file names.
SmallString<256> Filename(ToolChain::getInputFilename(Input));
llvm::sys::path::replace_extension(Filename, "cubin");
- return Filename.str();
+ return std::string(Filename.str());
}
void CudaToolChain::addClangTargetOptions(
@@ -614,10 +627,6 @@ void CudaToolChain::addClangTargetOptions(
if (DeviceOffloadingKind == Action::OFK_Cuda) {
CC1Args.push_back("-fcuda-is-device");
- if (DriverArgs.hasFlag(options::OPT_fcuda_flush_denormals_to_zero,
- options::OPT_fno_cuda_flush_denormals_to_zero, false))
- CC1Args.push_back("-fcuda-flush-denormals-to-zero");
-
if (DriverArgs.hasFlag(options::OPT_fcuda_approx_transcendentals,
options::OPT_fno_cuda_approx_transcendentals, false))
CC1Args.push_back("-fcuda-approx-transcendentals");
@@ -648,24 +657,30 @@ void CudaToolChain::addClangTargetOptions(
// 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()) {
- case CudaVersion::CUDA_101:
- PtxFeature = "+ptx64";
- break;
- case CudaVersion::CUDA_100:
- PtxFeature = "+ptx63";
- break;
- case CudaVersion::CUDA_92:
- PtxFeature = "+ptx61";
- break;
- case CudaVersion::CUDA_91:
- PtxFeature = "+ptx61";
- break;
- case CudaVersion::CUDA_90:
- PtxFeature = "+ptx60";
- break;
- default:
- PtxFeature = "+ptx42";
+ switch (CudaInstallation.version()) {
+ case CudaVersion::CUDA_110:
+ PtxFeature = "+ptx70";
+ break;
+ case CudaVersion::CUDA_102:
+ PtxFeature = "+ptx65";
+ break;
+ case CudaVersion::CUDA_101:
+ PtxFeature = "+ptx64";
+ break;
+ case CudaVersion::CUDA_100:
+ PtxFeature = "+ptx63";
+ break;
+ case CudaVersion::CUDA_92:
+ PtxFeature = "+ptx61";
+ break;
+ case CudaVersion::CUDA_91:
+ PtxFeature = "+ptx61";
+ break;
+ case CudaVersion::CUDA_90:
+ PtxFeature = "+ptx60";
+ break;
+ default:
+ PtxFeature = "+ptx42";
}
CC1Args.append({"-target-feature", PtxFeature});
if (DriverArgs.hasFlag(options::OPT_fcuda_short_ptr,
@@ -718,6 +733,21 @@ void CudaToolChain::addClangTargetOptions(
}
}
+llvm::DenormalMode CudaToolChain::getDefaultDenormalModeForType(
+ const llvm::opt::ArgList &DriverArgs, const JobAction &JA,
+ const llvm::fltSemantics *FPType) const {
+ if (JA.getOffloadingDeviceKind() == Action::OFK_Cuda) {
+ if (FPType && FPType == &llvm::APFloat::IEEEsingle() &&
+ DriverArgs.hasFlag(options::OPT_fcuda_flush_denormals_to_zero,
+ options::OPT_fno_cuda_flush_denormals_to_zero,
+ false))
+ return llvm::DenormalMode::getPreserveSign();
+ }
+
+ assert(JA.getOffloadingDeviceKind() != Action::OFK_Host);
+ 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) &&
@@ -748,7 +778,7 @@ void CudaToolChain::adjustDebugInfoKind(
void CudaToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
// Check our CUDA version if we're going to include the CUDA headers.
- if (!DriverArgs.hasArg(options::OPT_nocudainc) &&
+ if (!DriverArgs.hasArg(options::OPT_nogpuinc) &&
!DriverArgs.hasArg(options::OPT_no_cuda_version_check)) {
StringRef Arch = DriverArgs.getLastArgValue(options::OPT_march_EQ);
assert(!Arch.empty() && "Must have an explicit GPU arch.");
@@ -793,36 +823,6 @@ CudaToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
}
for (Arg *A : Args) {
- if (A->getOption().matches(options::OPT_Xarch__)) {
- // Skip this argument unless the architecture matches BoundArch
- if (BoundArch.empty() || A->getValue(0) != BoundArch)
- continue;
-
- unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
- unsigned Prev = Index;
- std::unique_ptr<Arg> XarchArg(Opts.ParseOneArg(Args, Index));
-
- // If the argument parsing failed or more than one argument was
- // consumed, the -Xarch_ argument's parameter tried to consume
- // extra arguments. Emit an error and ignore.
- //
- // We also want to disallow any options which would alter the
- // driver behavior; that isn't going to work in our model. We
- // use isDriverOption() as an approximation, although things
- // like -O4 are going to slip through.
- if (!XarchArg || Index > Prev + 1) {
- getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args)
- << A->getAsString(Args);
- continue;
- } else if (XarchArg->getOption().hasFlag(options::DriverOption)) {
- getDriver().Diag(diag::err_drv_invalid_Xarch_argument_isdriver)
- << A->getAsString(Args);
- continue;
- }
- XarchArg->setBaseArg(A);
- A = XarchArg.release();
- DAL->AddSynthesizedArg(A);
- }
DAL->append(A);
}
diff --git a/clang/lib/Driver/ToolChains/Cuda.h b/clang/lib/Driver/ToolChains/Cuda.h
index 4ee8b6f1fea99..873eb7338a30a 100644
--- a/clang/lib/Driver/ToolChains/Cuda.h
+++ b/clang/lib/Driver/ToolChains/Cuda.h
@@ -30,6 +30,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;
@@ -75,6 +77,10 @@ public:
std::string getLibDeviceFile(StringRef Gpu) const {
return LibDeviceMap.lookup(Gpu);
}
+ void WarnIfUnsupportedVersion();
+
+private:
+ void ParseCudaVersionFile(llvm::StringRef V);
};
namespace tools {
@@ -83,9 +89,7 @@ namespace NVPTX {
// Run ptxas, the NVPTX assembler.
class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
public:
- Assembler(const ToolChain &TC)
- : Tool("NVPTX::Assembler", "ptxas", TC, RF_Full, llvm::sys::WEM_UTF8,
- "--options-file") {}
+ Assembler(const ToolChain &TC) : Tool("NVPTX::Assembler", "ptxas", TC) {}
bool hasIntegratedCPP() const override { return false; }
@@ -99,9 +103,7 @@ class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
// assembly into a single output file.
class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
- Linker(const ToolChain &TC)
- : Tool("NVPTX::Linker", "fatbinary", TC, RF_Full, llvm::sys::WEM_UTF8,
- "--options-file") {}
+ Linker(const ToolChain &TC) : Tool("NVPTX::Linker", "fatbinary", TC) {}
bool hasIntegratedCPP() const override { return false; }
@@ -114,8 +116,7 @@ class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
class LLVM_LIBRARY_VISIBILITY OpenMPLinker : public Tool {
public:
OpenMPLinker(const ToolChain &TC)
- : Tool("NVPTX::OpenMPLinker", "nvlink", TC, RF_Full, llvm::sys::WEM_UTF8,
- "--options-file") {}
+ : Tool("NVPTX::OpenMPLinker", "nvlink", TC) {}
bool hasIntegratedCPP() const override { return false; }
@@ -149,6 +150,10 @@ public:
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;
+
// Never try to use the integrated assembler with CUDA; always fork out to
// ptxas.
bool useIntegratedAs() const override { return false; }
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index 344a14fe1ea7c..7b879f8cb6521 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -23,6 +23,7 @@
#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 <cstdlib> // ::getenv
@@ -147,7 +148,8 @@ void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
// asm_final spec is empty.
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Exec, CmdArgs, Inputs));
}
void darwin::MachOTool::anchor() {}
@@ -201,16 +203,11 @@ static bool shouldLinkerNotDedup(bool IsLinkerOnlyAction, const ArgList &Args) {
void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
ArgStringList &CmdArgs,
- const InputInfoList &Inputs) const {
+ const InputInfoList &Inputs,
+ unsigned Version[5]) const {
const Driver &D = getToolChain().getDriver();
const toolchains::MachO &MachOTC = getMachOToolChain();
- unsigned Version[5] = {0, 0, 0, 0, 0};
- if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) {
- if (!Driver::GetReleaseVersion(A->getValue(), Version))
- D.Diag(diag::err_drv_invalid_version_number) << A->getAsString(Args);
- }
-
// Newer linkers support -demangle. Pass it if supported and not disabled by
// the user.
if (Version[0] >= 100 && !Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
@@ -335,7 +332,7 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
Args.AddAllArgs(CmdArgs, options::OPT_init);
// Add the deployment target.
- if (!Version[0] || Version[0] >= 520)
+ if (Version[0] >= 520)
MachOTC.addPlatformVersionArgs(Args, CmdArgs);
else
MachOTC.addMinVersionArgs(Args, CmdArgs);
@@ -429,6 +426,75 @@ static bool isObjCRuntimeLinked(const ArgList &Args) {
return Args.hasArg(options::OPT_fobjc_link_runtime);
}
+static bool checkRemarksOptions(const Driver &D, const ArgList &Args,
+ const llvm::Triple &Triple) {
+ // When enabling remarks, we need to error if:
+ // * The remark file is specified but we're targeting multiple architectures,
+ // which means more than one remark file is being generated.
+ bool hasMultipleInvocations =
+ Args.getAllArgValues(options::OPT_arch).size() > 1;
+ bool hasExplicitOutputFile =
+ Args.getLastArg(options::OPT_foptimization_record_file_EQ);
+ if (hasMultipleInvocations && hasExplicitOutputFile) {
+ D.Diag(diag::err_drv_invalid_output_with_multiple_archs)
+ << "-foptimization-record-file";
+ return false;
+ }
+ return true;
+}
+
+static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs,
+ const llvm::Triple &Triple,
+ const InputInfo &Output, const JobAction &JA) {
+ StringRef Format = "yaml";
+ if (const Arg *A = Args.getLastArg(options::OPT_fsave_optimization_record_EQ))
+ Format = A->getValue();
+
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-lto-pass-remarks-output");
+ CmdArgs.push_back("-mllvm");
+
+ const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);
+ if (A) {
+ CmdArgs.push_back(A->getValue());
+ } else {
+ assert(Output.isFilename() && "Unexpected ld output.");
+ SmallString<128> F;
+ F = Output.getFilename();
+ F += ".opt.";
+ F += Format;
+
+ CmdArgs.push_back(Args.MakeArgString(F));
+ }
+
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) {
+ CmdArgs.push_back("-mllvm");
+ std::string Passes =
+ std::string("-lto-pass-remarks-filter=") + A->getValue();
+ CmdArgs.push_back(Args.MakeArgString(Passes));
+ }
+
+ if (!Format.empty()) {
+ CmdArgs.push_back("-mllvm");
+ Twine FormatArg = Twine("-lto-pass-remarks-format=") + Format;
+ CmdArgs.push_back(Args.MakeArgString(FormatArg));
+ }
+
+ if (getLastProfileUseArg(Args)) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-lto-pass-remarks-with-hotness");
+
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {
+ CmdArgs.push_back("-mllvm");
+ std::string Opt =
+ std::string("-lto-pass-remarks-hotness-threshold=") + A->getValue();
+ CmdArgs.push_back(Args.MakeArgString(Opt));
+ }
+ }
+}
+
void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -455,63 +521,26 @@ 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, Exec, CmdArgs, None));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::None(), Exec, CmdArgs, None));
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);
+ }
+
// I'm not sure why this particular decomposition exists in gcc, but
// we follow suite for ease of comparison.
- AddLinkArgs(C, Args, CmdArgs, Inputs);
+ AddLinkArgs(C, Args, CmdArgs, Inputs, Version);
- // For LTO, pass the name of the optimization record file and other
- // opt-remarks flags.
- if (Args.hasFlag(options::OPT_fsave_optimization_record,
- options::OPT_fsave_optimization_record_EQ,
- options::OPT_fno_save_optimization_record, false)) {
- CmdArgs.push_back("-mllvm");
- CmdArgs.push_back("-lto-pass-remarks-output");
- CmdArgs.push_back("-mllvm");
-
- SmallString<128> F;
- F = Output.getFilename();
- F += ".opt.";
- if (const Arg *A =
- Args.getLastArg(options::OPT_fsave_optimization_record_EQ))
- F += A->getValue();
- else
- F += "yaml";
-
- CmdArgs.push_back(Args.MakeArgString(F));
-
- if (getLastProfileUseArg(Args)) {
- CmdArgs.push_back("-mllvm");
- CmdArgs.push_back("-lto-pass-remarks-with-hotness");
-
- if (const Arg *A =
- Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {
- CmdArgs.push_back("-mllvm");
- std::string Opt =
- std::string("-lto-pass-remarks-hotness-threshold=") + A->getValue();
- CmdArgs.push_back(Args.MakeArgString(Opt));
- }
- }
-
- if (const Arg *A =
- Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) {
- CmdArgs.push_back("-mllvm");
- std::string Passes =
- std::string("-lto-pass-remarks-filter=") + A->getValue();
- CmdArgs.push_back(Args.MakeArgString(Passes));
- }
-
- if (const Arg *A =
- Args.getLastArg(options::OPT_fsave_optimization_record_EQ)) {
- CmdArgs.push_back("-mllvm");
- std::string Format =
- std::string("-lto-pass-remarks-format=") + A->getValue();
- CmdArgs.push_back(Args.MakeArgString(Format));
- }
- }
+ if (willEmitRemarks(Args) &&
+ checkRemarksOptions(getToolChain().getDriver(), Args,
+ getToolChain().getTriple()))
+ renderRemarksOptions(Args, CmdArgs, getToolChain().getTriple(), Output, JA);
// Propagate the -moutline flag to the linker in LTO.
if (Arg *A =
@@ -605,10 +634,12 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
getMachOToolChain().addProfileRTLibs(Args, CmdArgs);
- if (unsigned Parallelism =
- getLTOParallelism(Args, getToolChain().getDriver())) {
+ StringRef Parallelism = getLTOParallelism(Args, getToolChain().getDriver());
+ if (!Parallelism.empty()) {
CmdArgs.push_back("-mllvm");
- CmdArgs.push_back(Args.MakeArgString("-threads=" + Twine(Parallelism)));
+ unsigned NumThreads =
+ llvm::get_threadpool_strategy(Parallelism)->compute_thread_count();
+ CmdArgs.push_back(Args.MakeArgString("-threads=" + Twine(NumThreads)));
}
if (getToolChain().ShouldLinkCXXStdlib(Args))
@@ -655,9 +686,16 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ ResponseFileSupport ResponseSupport = ResponseFileSupport::AtFileUTF8();
+ if (Version[0] < 607) {
+ // For older versions of the linker, use the legacy filelist method instead.
+ ResponseSupport = {ResponseFileSupport::RF_FileList, llvm::sys::WEM_UTF8,
+ "-filelist"};
+ }
+
const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
- std::unique_ptr<Command> Cmd =
- std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs);
+ std::unique_ptr<Command> Cmd = std::make_unique<Command>(
+ JA, *this, ResponseSupport, Exec, CmdArgs, Inputs);
Cmd->setInputFileList(std::move(InputFileList));
C.addCommand(std::move(Cmd));
}
@@ -681,7 +719,8 @@ void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
}
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo"));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Exec, CmdArgs, Inputs));
}
void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA,
@@ -701,7 +740,8 @@ void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("dsymutil"));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Exec, CmdArgs, Inputs));
}
void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA,
@@ -724,7 +764,8 @@ void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump"));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Exec, CmdArgs, Inputs));
}
MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
@@ -738,7 +779,7 @@ MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
/// Darwin - Darwin tool chain for i386 and x86_64.
Darwin::Darwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: MachO(D, Triple, Args), TargetInitialized(false),
- CudaInstallation(D, Triple, Args) {}
+ CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) {}
types::ID MachO::LookupTypeForExtension(StringRef Ext) const {
types::ID Ty = ToolChain::LookupTypeForExtension(Ext);
@@ -790,6 +831,11 @@ void Darwin::AddCudaIncludeArgs(const ArgList &DriverArgs,
CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
}
+void Darwin::AddHIPIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
+}
+
// This is just a MachO name translation routine and there's no
// way to join this into ARMTargetParser without breaking all
// other assumptions. Maybe MachO should consider standardising
@@ -913,6 +959,10 @@ DarwinClang::DarwinClang(const Driver &D, const llvm::Triple &Triple,
: Darwin(D, Triple, Args) {}
void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const {
+ // Always error about undefined 'TARGET_OS_*' macros.
+ CC1Args.push_back("-Wundef-prefix=TARGET_OS_");
+ CC1Args.push_back("-Werror=undef-prefix");
+
// For modern targets, promote certain warnings to errors.
if (isTargetWatchOSBased() || getTriple().isArch64Bit()) {
// Always enable -Wdeprecated-objc-isa-usage and promote it
@@ -944,6 +994,8 @@ void DarwinClang::AddLinkARCArgs(const ArgList &Args,
// Avoid linking compatibility stubs on i386 mac.
if (isTargetMacOS() && getArch() == llvm::Triple::x86)
return;
+ if (isTargetAppleSiliconMac())
+ return;
ObjCRuntime runtime = getDefaultObjCRuntime(/*nonfragile*/ true);
@@ -1068,8 +1120,8 @@ StringRef Darwin::getPlatformFamily() const {
StringRef Darwin::getSDKName(StringRef isysroot) {
// Assume SDK has path: SOME_PATH/SDKs/PlatformXX.YY.sdk
- auto BeginSDK = llvm::sys::path::begin(isysroot);
- auto EndSDK = llvm::sys::path::end(isysroot);
+ auto BeginSDK = llvm::sys::path::rbegin(isysroot);
+ auto EndSDK = llvm::sys::path::rend(isysroot);
for (auto IT = BeginSDK; IT != EndSDK; ++IT) {
StringRef SDK = *IT;
if (SDK.endswith(".sdk"))
@@ -1131,7 +1183,8 @@ static void addSectalignToPage(const ArgList &Args, ArgStringList &CmdArgs,
void Darwin::addProfileRTLibs(const ArgList &Args,
ArgStringList &CmdArgs) const {
- if (!needsProfileRT(Args)) return;
+ if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args))
+ return;
AddLinkRuntimeLib(Args, CmdArgs, "profile",
RuntimeLinkOptions(RLO_AlwaysLink | RLO_FirstLink));
@@ -1146,6 +1199,7 @@ void Darwin::addProfileRTLibs(const ArgList &Args,
addExportedSymbol(CmdArgs, "___gcov_flush");
addExportedSymbol(CmdArgs, "_flush_fn_list");
addExportedSymbol(CmdArgs, "_writeout_fn_list");
+ addExportedSymbol(CmdArgs, "_reset_fn_list");
} else {
addExportedSymbol(CmdArgs, "___llvm_profile_filename");
addExportedSymbol(CmdArgs, "___llvm_profile_raw_version");
@@ -1270,17 +1324,17 @@ static std::string getSystemOrSDKMacOSVersion(StringRef MacOSSDKVersion) {
unsigned Major, Minor, Micro;
llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
if (!SystemTriple.isMacOSX())
- return MacOSSDKVersion;
+ return std::string(MacOSSDKVersion);
SystemTriple.getMacOSXVersion(Major, Minor, Micro);
VersionTuple SystemVersion(Major, Minor, Micro);
bool HadExtra;
if (!Driver::GetReleaseVersion(MacOSSDKVersion, Major, Minor, Micro,
HadExtra))
- return MacOSSDKVersion;
+ return std::string(MacOSSDKVersion);
VersionTuple SDKVersion(Major, Minor, Micro);
if (SDKVersion > SystemVersion)
return SystemVersion.getAsString();
- return MacOSSDKVersion;
+ return std::string(MacOSSDKVersion);
}
namespace {
@@ -1320,7 +1374,7 @@ struct DarwinPlatform {
void setOSVersion(StringRef S) {
assert(Kind == TargetArg && "Unexpected kind!");
- OSVersion = S;
+ OSVersion = std::string(S);
}
bool hasOSVersion() const { return HasOSVersion; }
@@ -1577,7 +1631,7 @@ inferDeploymentTargetFromSDK(DerivedArgList &Args,
size_t StartVer = SDK.find_first_of("0123456789");
size_t EndVer = SDK.find_last_of("0123456789");
if (StartVer != StringRef::npos && EndVer > StartVer)
- Version = SDK.slice(StartVer, EndVer + 1);
+ Version = std::string(SDK.slice(StartVer, EndVer + 1));
}
if (Version.empty())
return None;
@@ -1643,8 +1697,16 @@ inferDeploymentTargetFromArch(DerivedArgList &Args, const Darwin &Toolchain,
llvm::Triple::OSType OSTy = llvm::Triple::UnknownOS;
StringRef MachOArchName = Toolchain.getMachOArchName(Args);
- if (MachOArchName == "armv7" || MachOArchName == "armv7s" ||
- MachOArchName == "arm64")
+ if (MachOArchName == "arm64") {
+#if __arm64__
+ // A clang running on an Apple Silicon mac defaults
+ // to building for mac when building for arm64 rather than
+ // defaulting to iOS.
+ OSTy = llvm::Triple::MacOSX;
+#else
+ OSTy = llvm::Triple::IOS;
+#endif
+ } else if (MachOArchName == "armv7" || MachOArchName == "armv7s")
OSTy = llvm::Triple::IOS;
else if (MachOArchName == "armv7k" || MachOArchName == "arm64_32")
OSTy = llvm::Triple::WatchOS;
@@ -1793,7 +1855,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
if (Platform == MacOS) {
if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
Micro, HadExtra) ||
- HadExtra || Major != 10 || Minor >= 100 || Micro >= 100)
+ HadExtra || Major < 10 || Major >= 100 || Minor >= 100 || Micro >= 100)
getDriver().Diag(diag::err_drv_invalid_version_number)
<< OSTarget->getAsString(Args, Opts);
} else if (Platform == IPhoneOS) {
@@ -1870,7 +1932,10 @@ void DarwinClang::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs
bool NoStdInc = DriverArgs.hasArg(options::OPT_nostdinc);
bool NoStdlibInc = DriverArgs.hasArg(options::OPT_nostdlibinc);
- bool NoBuiltinInc = DriverArgs.hasArg(options::OPT_nobuiltininc);
+ bool NoBuiltinInc = DriverArgs.hasFlag(
+ options::OPT_nobuiltininc, options::OPT_ibuiltininc, /*Default=*/false);
+ bool ForceBuiltinInc = DriverArgs.hasFlag(
+ options::OPT_ibuiltininc, options::OPT_nobuiltininc, /*Default=*/false);
// Add <sysroot>/usr/local/include
if (!NoStdInc && !NoStdlibInc) {
@@ -1880,7 +1945,7 @@ void DarwinClang::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs
}
// Add the Clang builtin headers (<resource>/include)
- if (!NoStdInc && !NoBuiltinInc) {
+ if (!(NoStdInc && !ForceBuiltinInc) && !NoBuiltinInc) {
SmallString<128> P(D.ResourceDir);
llvm::sys::path::append(P, "include");
addSystemInclude(DriverArgs, CC1Args, P);
@@ -1896,7 +1961,7 @@ void DarwinClang::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs
CIncludeDirs.split(dirs, ":");
for (llvm::StringRef dir : dirs) {
llvm::StringRef Prefix =
- llvm::sys::path::is_absolute(dir) ? llvm::StringRef(Sysroot) : "";
+ llvm::sys::path::is_absolute(dir) ? "" : llvm::StringRef(Sysroot);
addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
}
} else {
@@ -2129,32 +2194,7 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
continue;
Arg *OriginalArg = A;
- unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
- unsigned Prev = Index;
- std::unique_ptr<Arg> XarchArg(Opts.ParseOneArg(Args, Index));
-
- // If the argument parsing failed or more than one argument was
- // consumed, the -Xarch_ argument's parameter tried to consume
- // extra arguments. Emit an error and ignore.
- //
- // We also want to disallow any options which would alter the
- // driver behavior; that isn't going to work in our model. We
- // use isDriverOption() as an approximation, although things
- // like -O4 are going to slip through.
- if (!XarchArg || Index > Prev + 1) {
- getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args)
- << A->getAsString(Args);
- continue;
- } else if (XarchArg->getOption().hasFlag(options::DriverOption)) {
- getDriver().Diag(diag::err_drv_invalid_Xarch_argument_isdriver)
- << A->getAsString(Args);
- continue;
- }
-
- XarchArg->setBaseArg(A);
-
- A = XarchArg.release();
- DAL->AddSynthesizedArg(A);
+ TranslateXarchArgs(Args, A, DAL);
// Linker input arguments require custom handling. The problem is that we
// have already constructed the phase actions, so we can not treat them as
@@ -2369,6 +2409,10 @@ void Darwin::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
OS << "-target-sdk-version=" << SDKInfo->getVersion();
CC1Args.push_back(DriverArgs.MakeArgString(OS.str()));
}
+
+ // Enable compatibility mode for NSItemProviderCompletionHandler in
+ // Foundation/NSItemProvider.h.
+ CC1Args.push_back("-fcompatibility-qualified-id-block-type-checking");
}
DerivedArgList *
@@ -2511,6 +2555,9 @@ void Darwin::addMinVersionArgs(const ArgList &Args,
CmdArgs.push_back("-macosx_version_min");
}
+ VersionTuple MinTgtVers = getEffectiveTriple().getMinimumSupportedOSVersion();
+ if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
+ TargetVersion = MinTgtVers;
CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
}
@@ -2543,6 +2590,9 @@ void Darwin::addPlatformVersionArgs(const llvm::opt::ArgList &Args,
PlatformName += "-simulator";
CmdArgs.push_back(Args.MakeArgString(PlatformName));
VersionTuple TargetVersion = getTargetVersion().withoutBuild();
+ VersionTuple MinTgtVers = getEffectiveTriple().getMinimumSupportedOSVersion();
+ if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
+ TargetVersion = MinTgtVers;
CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
if (SDKInfo) {
VersionTuple SDKVersion = SDKInfo->getVersion().withoutBuild();
@@ -2553,98 +2603,102 @@ void Darwin::addPlatformVersionArgs(const llvm::opt::ArgList &Args,
}
}
-void Darwin::addStartObjectFileArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const {
- // Derived from startfile spec.
- if (Args.hasArg(options::OPT_dynamiclib)) {
- // Derived from darwin_dylib1 spec.
- if (isTargetWatchOSBased()) {
- ; // watchOS does not need dylib1.o.
- } else if (isTargetIOSSimulator()) {
- ; // iOS simulator does not need dylib1.o.
- } else if (isTargetIPhoneOS()) {
- if (isIPhoneOSVersionLT(3, 1))
- CmdArgs.push_back("-ldylib1.o");
+// Add additional link args for the -dynamiclib option.
+static void addDynamicLibLinkArgs(const Darwin &D, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ // Derived from darwin_dylib1 spec.
+ if (D.isTargetIPhoneOS()) {
+ if (D.isIPhoneOSVersionLT(3, 1))
+ CmdArgs.push_back("-ldylib1.o");
+ return;
+ }
+
+ if (!D.isTargetMacOS())
+ return;
+ if (D.isMacosxVersionLT(10, 5))
+ CmdArgs.push_back("-ldylib1.o");
+ else if (D.isMacosxVersionLT(10, 6))
+ CmdArgs.push_back("-ldylib1.10.5.o");
+}
+
+// Add additional link args for the -bundle option.
+static void addBundleLinkArgs(const Darwin &D, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ if (Args.hasArg(options::OPT_static))
+ return;
+ // Derived from darwin_bundle1 spec.
+ if ((D.isTargetIPhoneOS() && D.isIPhoneOSVersionLT(3, 1)) ||
+ (D.isTargetMacOS() && D.isMacosxVersionLT(10, 6)))
+ CmdArgs.push_back("-lbundle1.o");
+}
+
+// Add additional link args for the -pg option.
+static void addPgProfilingLinkArgs(const Darwin &D, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ if (D.isTargetMacOS() && D.isMacosxVersionLT(10, 9)) {
+ if (Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_object) ||
+ Args.hasArg(options::OPT_preload)) {
+ CmdArgs.push_back("-lgcrt0.o");
} else {
- if (isMacosxVersionLT(10, 5))
- CmdArgs.push_back("-ldylib1.o");
- else if (isMacosxVersionLT(10, 6))
- CmdArgs.push_back("-ldylib1.10.5.o");
+ CmdArgs.push_back("-lgcrt1.o");
+
+ // darwin_crt2 spec is empty.
}
+ // By default on OS X 10.8 and later, we don't link with a crt1.o
+ // file and the linker knows to use _main as the entry point. But,
+ // when compiling with -pg, we need to link with the gcrt1.o file,
+ // so pass the -no_new_main option to tell the linker to use the
+ // "start" symbol as the entry point.
+ if (!D.isMacosxVersionLT(10, 8))
+ CmdArgs.push_back("-no_new_main");
} else {
- if (Args.hasArg(options::OPT_bundle)) {
- if (!Args.hasArg(options::OPT_static)) {
- // Derived from darwin_bundle1 spec.
- if (isTargetWatchOSBased()) {
- ; // watchOS does not need bundle1.o.
- } else if (isTargetIOSSimulator()) {
- ; // iOS simulator does not need bundle1.o.
- } else if (isTargetIPhoneOS()) {
- if (isIPhoneOSVersionLT(3, 1))
- CmdArgs.push_back("-lbundle1.o");
- } else {
- if (isMacosxVersionLT(10, 6))
- CmdArgs.push_back("-lbundle1.o");
- }
- }
- } else {
- if (Args.hasArg(options::OPT_pg) && SupportsProfiling()) {
- if (isTargetMacOS() && isMacosxVersionLT(10, 9)) {
- if (Args.hasArg(options::OPT_static) ||
- Args.hasArg(options::OPT_object) ||
- Args.hasArg(options::OPT_preload)) {
- CmdArgs.push_back("-lgcrt0.o");
- } else {
- CmdArgs.push_back("-lgcrt1.o");
-
- // darwin_crt2 spec is empty.
- }
- // By default on OS X 10.8 and later, we don't link with a crt1.o
- // file and the linker knows to use _main as the entry point. But,
- // when compiling with -pg, we need to link with the gcrt1.o file,
- // so pass the -no_new_main option to tell the linker to use the
- // "start" symbol as the entry point.
- if (isTargetMacOS() && !isMacosxVersionLT(10, 8))
- CmdArgs.push_back("-no_new_main");
- } else {
- getDriver().Diag(diag::err_drv_clang_unsupported_opt_pg_darwin)
- << isTargetMacOS();
- }
- } else {
- if (Args.hasArg(options::OPT_static) ||
- Args.hasArg(options::OPT_object) ||
- Args.hasArg(options::OPT_preload)) {
- CmdArgs.push_back("-lcrt0.o");
- } else {
- // Derived from darwin_crt1 spec.
- if (isTargetWatchOSBased()) {
- ; // watchOS does not need crt1.o.
- } else if (isTargetIOSSimulator()) {
- ; // iOS simulator does not need crt1.o.
- } else if (isTargetIPhoneOS()) {
- if (getArch() == llvm::Triple::aarch64)
- ; // iOS does not need any crt1 files for arm64
- else if (isIPhoneOSVersionLT(3, 1))
- CmdArgs.push_back("-lcrt1.o");
- else if (isIPhoneOSVersionLT(6, 0))
- CmdArgs.push_back("-lcrt1.3.1.o");
- } else {
- if (isMacosxVersionLT(10, 5))
- CmdArgs.push_back("-lcrt1.o");
- else if (isMacosxVersionLT(10, 6))
- CmdArgs.push_back("-lcrt1.10.5.o");
- else if (isMacosxVersionLT(10, 8))
- CmdArgs.push_back("-lcrt1.10.6.o");
-
- // darwin_crt2 spec is empty.
- }
- }
- }
- }
+ D.getDriver().Diag(diag::err_drv_clang_unsupported_opt_pg_darwin)
+ << D.isTargetMacOS();
}
+}
+
+static void addDefaultCRTLinkArgs(const Darwin &D, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ // Derived from darwin_crt1 spec.
+ if (D.isTargetIPhoneOS()) {
+ if (D.getArch() == llvm::Triple::aarch64)
+ ; // iOS does not need any crt1 files for arm64
+ else if (D.isIPhoneOSVersionLT(3, 1))
+ CmdArgs.push_back("-lcrt1.o");
+ else if (D.isIPhoneOSVersionLT(6, 0))
+ CmdArgs.push_back("-lcrt1.3.1.o");
+ return;
+ }
+
+ if (!D.isTargetMacOS())
+ return;
+ if (D.isMacosxVersionLT(10, 5))
+ CmdArgs.push_back("-lcrt1.o");
+ else if (D.isMacosxVersionLT(10, 6))
+ CmdArgs.push_back("-lcrt1.10.5.o");
+ else if (D.isMacosxVersionLT(10, 8))
+ CmdArgs.push_back("-lcrt1.10.6.o");
+ // darwin_crt2 spec is empty.
+}
+
+void Darwin::addStartObjectFileArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ // Derived from startfile spec.
+ if (Args.hasArg(options::OPT_dynamiclib))
+ addDynamicLibLinkArgs(*this, Args, CmdArgs);
+ else if (Args.hasArg(options::OPT_bundle))
+ addBundleLinkArgs(*this, Args, CmdArgs);
+ else if (Args.hasArg(options::OPT_pg) && SupportsProfiling())
+ addPgProfilingLinkArgs(*this, Args, CmdArgs);
+ else if (Args.hasArg(options::OPT_static) ||
+ Args.hasArg(options::OPT_object) ||
+ Args.hasArg(options::OPT_preload))
+ CmdArgs.push_back("-lcrt0.o");
+ else
+ addDefaultCRTLinkArgs(*this, Args, CmdArgs);
- if (!isTargetIPhoneOS() && Args.hasArg(options::OPT_shared_libgcc) &&
- !isTargetWatchOS() && isMacosxVersionLT(10, 5)) {
+ if (isTargetMacOS() && Args.hasArg(options::OPT_shared_libgcc) &&
+ isMacosxVersionLT(10, 5)) {
const char *Str = Args.MakeArgString(GetFilePath("crt3.o"));
CmdArgs.push_back(Str);
}
@@ -2667,6 +2721,7 @@ SanitizerMask Darwin::getSupportedSanitizers() const {
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
// C++11 support. The same is true of iOS prior to version 5. These OS'es are
@@ -2687,4 +2742,5 @@ SanitizerMask Darwin::getSupportedSanitizers() const {
void Darwin::printVerboseInfo(raw_ostream &OS) const {
CudaInstallation.print(OS);
+ RocmInstallation.print(OS);
}
diff --git a/clang/lib/Driver/ToolChains/Darwin.h b/clang/lib/Driver/ToolChains/Darwin.h
index 1b193a4c4eb96..64c252efea7df 100644
--- a/clang/lib/Driver/ToolChains/Darwin.h
+++ b/clang/lib/Driver/ToolChains/Darwin.h
@@ -10,6 +10,7 @@
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H
#include "Cuda.h"
+#include "ROCm.h"
#include "clang/Driver/DarwinSDKInfo.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
@@ -40,13 +41,8 @@ protected:
}
public:
- MachOTool(
- const char *Name, const char *ShortName, const ToolChain &TC,
- ResponseFileSupport ResponseSupport = RF_None,
- llvm::sys::WindowsEncodingMethod ResponseEncoding = llvm::sys::WEM_UTF8,
- const char *ResponseFlag = "@")
- : Tool(Name, ShortName, TC, ResponseSupport, ResponseEncoding,
- ResponseFlag) {}
+ MachOTool(const char *Name, const char *ShortName, const ToolChain &TC)
+ : Tool(Name, ShortName, TC) {}
};
class LLVM_LIBRARY_VISIBILITY Assembler : public MachOTool {
@@ -66,12 +62,10 @@ 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) const;
+ const InputInfoList &Inputs, unsigned Version[5]) const;
public:
- Linker(const ToolChain &TC)
- : MachOTool("darwin::Linker", "linker", TC, RF_FileList,
- llvm::sys::WEM_UTF8, "-filelist") {}
+ Linker(const ToolChain &TC) : MachOTool("darwin::Linker", "linker", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
@@ -300,6 +294,7 @@ public:
mutable Optional<DarwinSDKInfo> SDKInfo;
CudaInstallationDetector CudaInstallation;
+ RocmInstallationDetector RocmInstallation;
private:
void AddDeploymentTarget(llvm::opt::DerivedArgList &Args) const;
@@ -357,6 +352,7 @@ protected:
const_cast<Darwin *>(this)->setTripleEnvironment(llvm::Triple::Simulator);
}
+public:
bool isTargetIPhoneOS() const {
assert(TargetInitialized && "Target not initialized!");
return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) &&
@@ -409,6 +405,17 @@ protected:
return TargetPlatform == MacOS;
}
+ bool isTargetMacOSBased() const {
+ assert(TargetInitialized && "Target not initialized!");
+ // FIXME (Alex L): Add remaining MacCatalyst suppport.
+ return TargetPlatform == MacOS;
+ }
+
+ bool isTargetAppleSiliconMac() const {
+ assert(TargetInitialized && "Target not initialized!");
+ return isTargetMacOSBased() && getArch() == llvm::Triple::aarch64;
+ }
+
bool isTargetInitialized() const { return TargetInitialized; }
VersionTuple getTargetVersion() const {
@@ -422,11 +429,20 @@ protected:
return TargetVersion < VersionTuple(V0, V1, V2);
}
+ /// Returns true if the minimum supported macOS version for the slice that's
+ /// being built is less than the specified version. If there's no minimum
+ /// supported macOS version, the deployment target version is compared to the
+ /// specifed version instead.
bool isMacosxVersionLT(unsigned V0, unsigned V1 = 0, unsigned V2 = 0) const {
- assert(isTargetMacOS() && "Unexpected call for non OS X target!");
- return TargetVersion < VersionTuple(V0, V1, V2);
+ assert(isTargetMacOS() && getTriple().isMacOSX() &&
+ "Unexpected call for non OS X target!");
+ VersionTuple MinVers = getTriple().getMinimumSupportedOSVersion();
+ return (!MinVers.empty() && MinVers > TargetVersion
+ ? MinVers
+ : TargetVersion) < VersionTuple(V0, V1, V2);
}
+protected:
/// Return true if c++17 aligned allocation/deallocation functions are not
/// implemented in the c++ standard library of the deployment target we are
/// targeting.
@@ -461,6 +477,8 @@ public:
void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+ void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
bool UseObjCMixedDispatch() const override {
// This is only used with the non-fragile ABI and non-legacy dispatch.
diff --git a/clang/lib/Driver/ToolChains/DragonFly.cpp b/clang/lib/Driver/ToolChains/DragonFly.cpp
index 424331fbc6fe0..88dd0c899d8a8 100644
--- a/clang/lib/Driver/ToolChains/DragonFly.cpp
+++ b/clang/lib/Driver/ToolChains/DragonFly.cpp
@@ -45,7 +45,8 @@ void dragonfly::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(II.getFilename());
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
}
void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -169,7 +170,8 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
getToolChain().addProfileRTLibs(Args, CmdArgs);
const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
}
/// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.
diff --git a/clang/lib/Driver/ToolChains/DragonFly.h b/clang/lib/Driver/ToolChains/DragonFly.h
index 7e76904f10558..3ed5acefaefb5 100644
--- a/clang/lib/Driver/ToolChains/DragonFly.h
+++ b/clang/lib/Driver/ToolChains/DragonFly.h
@@ -18,10 +18,10 @@ namespace driver {
namespace tools {
/// dragonfly -- Directly call GNU Binutils assembler and linker
namespace dragonfly {
-class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
public:
Assembler(const ToolChain &TC)
- : GnuTool("dragonfly::Assembler", "assembler", TC) {}
+ : Tool("dragonfly::Assembler", "assembler", TC) {}
bool hasIntegratedCPP() const override { return false; }
@@ -31,9 +31,9 @@ public:
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
- Linker(const ToolChain &TC) : GnuTool("dragonfly::Linker", "linker", TC) {}
+ Linker(const ToolChain &TC) : Tool("dragonfly::Linker", "linker", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 9b9eb81fa111d..80f6db7ea6427 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -70,10 +70,10 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
const auto& D = C.getDriver();
const char* Exec = Args.MakeArgString(D.GetProgramPath("flang", TC));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs));
}
-Flang::Flang(const ToolChain &TC)
- : Tool("flang", "flang frontend", TC, RF_Full) {}
+Flang::Flang(const ToolChain &TC) : Tool("flang", "flang frontend", TC) {}
Flang::~Flang() {}
diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp
index c5c6f530f48c0..909ac5e992129 100644
--- a/clang/lib/Driver/ToolChains/FreeBSD.cpp
+++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp
@@ -99,7 +99,8 @@ void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
case llvm::Triple::sparcel:
case llvm::Triple::sparcv9: {
std::string CPU = getCPUName(Args, getToolChain().getTriple());
- CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
+ CmdArgs.push_back(
+ sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
break;
}
@@ -127,7 +128,8 @@ void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(II.getFilename());
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
}
void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -275,7 +277,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (D.isUsingLTO()) {
assert(!Inputs.empty() && "Must have at least one input.");
- AddGoldPlugin(ToolChain, Args, CmdArgs, Output, Inputs[0],
+ addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs[0],
D.getLTOMode() == LTOK_Thin);
}
@@ -357,7 +359,8 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
ToolChain.addProfileRTLibs(Args, CmdArgs);
const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
}
/// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly.
@@ -388,6 +391,12 @@ unsigned FreeBSD::GetDefaultDwarfVersion() const {
return 4;
}
+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 {
@@ -416,6 +425,11 @@ void FreeBSD::AddCudaIncludeArgs(const ArgList &DriverArgs,
CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
}
+void FreeBSD::AddHIPIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
+}
+
Tool *FreeBSD::buildAssembler() const {
return new tools::freebsd::Assembler(*this);
}
diff --git a/clang/lib/Driver/ToolChains/FreeBSD.h b/clang/lib/Driver/ToolChains/FreeBSD.h
index 84bdbfd9a3125..abc0876cef260 100644
--- a/clang/lib/Driver/ToolChains/FreeBSD.h
+++ b/clang/lib/Driver/ToolChains/FreeBSD.h
@@ -19,10 +19,10 @@ namespace tools {
/// freebsd -- Directly call GNU Binutils assembler and linker
namespace freebsd {
-class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
public:
Assembler(const ToolChain &TC)
- : GnuTool("freebsd::Assembler", "assembler", TC) {}
+ : Tool("freebsd::Assembler", "assembler", TC) {}
bool hasIntegratedCPP() const override { return false; }
@@ -32,9 +32,9 @@ public:
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
- Linker(const ToolChain &TC) : GnuTool("freebsd::Linker", "linker", TC) {}
+ Linker(const ToolChain &TC) : Tool("freebsd::Linker", "linker", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
@@ -59,16 +59,20 @@ public:
bool IsObjCNonFragileABIDefault() const override { return true; }
CXXStdlibType GetDefaultCXXStdlibType() 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;
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
void AddCudaIncludeArgs(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::ExceptionHandling GetExceptionModel(
- const llvm::opt::ArgList &Args) 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;
SanitizerMask getSupportedSanitizers() const override;
diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp
index 808d0408d0d4c..94e025e3055a3 100644
--- a/clang/lib/Driver/ToolChains/Fuchsia.cpp
+++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp
@@ -15,6 +15,7 @@
#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"
@@ -47,6 +48,9 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.ClaimAllArgs(options::OPT_w);
CmdArgs.push_back("-z");
+ CmdArgs.push_back("max-page-size=4096");
+
+ CmdArgs.push_back("-z");
CmdArgs.push_back("now");
const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
@@ -56,6 +60,7 @@ 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("--pack-dyn-relocs=relr");
}
if (!D.SysRoot.empty())
@@ -111,7 +116,7 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (D.isUsingLTO()) {
assert(!Inputs.empty() && "Must have at least one input.");
- AddGoldPlugin(ToolChain, Args, CmdArgs, Output, Inputs[0],
+ addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs[0],
D.getLTOMode() == LTOK_Thin);
}
@@ -159,7 +164,8 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lc");
}
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Exec, CmdArgs, Inputs));
}
/// Fuchsia - Fuchsia tool chain which can call as(1) and ld(1) directly.
@@ -174,7 +180,7 @@ 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(P.str());
+ getFilePaths().push_back(std::string(P.str()));
}
auto FilePaths = [&](const Multilib &M) -> std::vector<std::string> {
@@ -183,7 +189,7 @@ Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple,
if (auto CXXStdlibPath = getCXXStdlibPath()) {
SmallString<128> P(*CXXStdlibPath);
llvm::sys::path::append(P, M.gccSuffix());
- FP.push_back(P.str());
+ FP.push_back(std::string(P.str()));
}
}
return FP;
@@ -289,7 +295,7 @@ void Fuchsia::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
CIncludeDirs.split(dirs, ":");
for (StringRef dir : dirs) {
StringRef Prefix =
- llvm::sys::path::is_absolute(dir) ? StringRef(D.SysRoot) : "";
+ llvm::sys::path::is_absolute(dir) ? "" : StringRef(D.SysRoot);
addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
}
return;
@@ -340,6 +346,7 @@ SanitizerMask Fuchsia::getSupportedSanitizers() const {
Res |= SanitizerKind::PointerSubtract;
Res |= SanitizerKind::Fuzzer;
Res |= SanitizerKind::FuzzerNoLink;
+ Res |= SanitizerKind::Leak;
Res |= SanitizerKind::SafeStack;
Res |= SanitizerKind::Scudo;
return Res;
@@ -360,3 +367,13 @@ SanitizerMask Fuchsia::getDefaultSanitizers() const {
}
return Res;
}
+
+void Fuchsia::addProfileRTLibs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const {
+ // Add linker option -u__llvm_profile_runtime to cause runtime
+ // initialization module to be linked in.
+ if (needsProfileRT(Args))
+ CmdArgs.push_back(Args.MakeArgString(
+ Twine("-u", llvm::getInstrProfRuntimeHookVarName())));
+ ToolChain::addProfileRTLibs(Args, CmdArgs);
+}
diff --git a/clang/lib/Driver/ToolChains/Fuchsia.h b/clang/lib/Driver/ToolChains/Fuchsia.h
index fee0e018f3ce3..3159a54bda065 100644
--- a/clang/lib/Driver/ToolChains/Fuchsia.h
+++ b/clang/lib/Driver/ToolChains/Fuchsia.h
@@ -69,6 +69,9 @@ public:
SanitizerMask getSupportedSanitizers() const override;
SanitizerMask getDefaultSanitizers() const override;
+ void addProfileRTLibs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+
RuntimeLibType
GetRuntimeLibType(const llvm::opt::ArgList &Args) const override;
CXXStdlibType
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index da197e476621a..c8a7fce07ef1c 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -35,8 +35,7 @@ using namespace clang;
using namespace llvm::opt;
using tools::addMultilibFlag;
-
-void tools::GnuTool::anchor() {}
+using tools::addPathIfExists;
static bool forwardToGCC(const Option &O) {
// Don't forward inputs from the original command line. They are added from
@@ -189,7 +188,8 @@ void tools::gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
GCCName = "gcc";
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
}
void tools::gcc::Preprocessor::RenderExtraToolArgs(
@@ -304,12 +304,14 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
if (T.getEnvironment() == llvm::Triple::GNUX32)
return "elf32_x86_64";
return "elf_x86_64";
+ case llvm::Triple::ve:
+ return "elf64ve";
default:
return nullptr;
}
}
-static bool getPIE(const ArgList &Args, const toolchains::Linux &ToolChain) {
+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;
@@ -317,17 +319,16 @@ static bool getPIE(const ArgList &Args, const toolchains::Linux &ToolChain) {
Arg *A = Args.getLastArg(options::OPT_pie, options::OPT_no_pie,
options::OPT_nopie);
if (!A)
- return ToolChain.isPIEDefault();
+ return TC.isPIEDefault();
return A->getOption().matches(options::OPT_pie);
}
-static bool getStaticPIE(const ArgList &Args,
- const toolchains::Linux &ToolChain) {
+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)) {
- const Driver &D = ToolChain.getDriver();
+ 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);
@@ -341,13 +342,55 @@ static bool getStatic(const ArgList &Args) {
!Args.hasArg(options::OPT_static_pie);
}
+void tools::gnutools::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);
+
+ // GNU ar tool command "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());
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
+
+ // Delete old output archive file if it already exists before generating a new
+ // archive file.
+ 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::AtFileCurCP(), Exec, CmdArgs, Inputs));
+}
+
void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
- const toolchains::Linux &ToolChain =
- static_cast<const toolchains::Linux &>(getToolChain());
+ // FIXME: The Linker class constructor takes a ToolChain and not a
+ // 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 Driver &D = ToolChain.getDriver();
const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
@@ -355,6 +398,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const llvm::Triple::ArchType Arch = ToolChain.getArch();
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);
@@ -418,8 +462,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (isAndroid)
CmdArgs.push_back("--warn-shared-textrel");
- for (const auto &Opt : ToolChain.ExtraOpts)
- CmdArgs.push_back(Opt.c_str());
+ ToolChain.addExtraOpts(CmdArgs);
CmdArgs.push_back("--eh-frame-hdr");
@@ -446,10 +489,9 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-export-dynamic");
if (!Args.hasArg(options::OPT_shared) && !IsStaticPIE) {
- const std::string Loader =
- D.DyldPrefix + ToolChain.getDynamicLinker(Args);
CmdArgs.push_back("-dynamic-linker");
- CmdArgs.push_back(Args.MakeArgString(Loader));
+ CmdArgs.push_back(Args.MakeArgString(Twine(D.DyldPrefix) +
+ ToolChain.getDynamicLinker(Args)));
}
}
@@ -475,6 +517,11 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
}
+ if (IsVE) {
+ CmdArgs.push_back("-z");
+ CmdArgs.push_back("max-page-size=0x4000000");
+ }
+
if (IsIAMCU)
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
else if (HasCRTBeginEndFiles) {
@@ -502,7 +549,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
// Add crtfastmath.o if available and fast math is enabled.
- ToolChain.AddFastMathRuntimeIfAvailable(Args, CmdArgs);
+ ToolChain.addFastMathRuntimeIfAvailable(Args, CmdArgs);
}
Args.AddAllArgs(CmdArgs, options::OPT_L);
@@ -512,7 +559,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (D.isUsingLTO()) {
assert(!Inputs.empty() && "Must have at least one input.");
- AddGoldPlugin(ToolChain, Args, CmdArgs, Output, Inputs[0],
+ addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs[0],
D.getLTOMode() == LTOK_Thin);
}
@@ -623,12 +670,11 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- // Add HIP offloading linker script args if required.
- AddHIPLinkerScript(getToolChain(), C, Output, Inputs, Args, CmdArgs, JA,
- *this);
+ Args.AddAllArgs(CmdArgs, options::OPT_T);
const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
}
void tools::gnutools::Assembler::ConstructJob(Compilation &C,
@@ -646,6 +692,7 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
llvm::Reloc::Model RelocationModel;
unsigned PICLevel;
bool IsPIE;
+ const char *DefaultAssembler = "as";
std::tie(RelocationModel, PICLevel, IsPIE) =
ParsePICArgs(getToolChain(), Args);
@@ -866,6 +913,8 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName));
break;
}
+ case llvm::Triple::ve:
+ DefaultAssembler = "nas";
}
for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ,
@@ -890,8 +939,10 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
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, Exec, CmdArgs, Inputs));
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath(DefaultAssembler));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
// Handle the debug info splitting at object creation time if we're
// creating an object.
@@ -1527,7 +1578,7 @@ static void findRISCVBareMetalMultilibs(const Driver &D,
};
// currently only support the set of multilibs like riscv-gnu-toolchain does.
// TODO: support MULTILIB_REUSE
- SmallVector<RiscvMultilib, 8> RISCVMultilibSet = {
+ constexpr RiscvMultilib RISCVMultilibSet[] = {
{"rv32i", "ilp32"}, {"rv32im", "ilp32"}, {"rv32iac", "ilp32"},
{"rv32imac", "ilp32"}, {"rv32imafc", "ilp32f"}, {"rv64imac", "lp64"},
{"rv64imafdc", "lp64d"}};
@@ -1767,7 +1818,7 @@ Generic_GCC::GCCVersion Generic_GCC::GCCVersion::Parse(StringRef VersionText) {
StringRef MinorStr = Second.first;
if (Second.second.empty()) {
if (size_t EndNumber = MinorStr.find_first_not_of("0123456789")) {
- GoodVersion.PatchSuffix = MinorStr.substr(EndNumber);
+ GoodVersion.PatchSuffix = std::string(MinorStr.substr(EndNumber));
MinorStr = MinorStr.slice(0, EndNumber);
}
}
@@ -1793,7 +1844,7 @@ Generic_GCC::GCCVersion Generic_GCC::GCCVersion::Parse(StringRef VersionText) {
if (PatchText.slice(0, EndNumber).getAsInteger(10, GoodVersion.Patch) ||
GoodVersion.Patch < 0)
return BadVersion;
- GoodVersion.PatchSuffix = PatchText.substr(EndNumber);
+ GoodVersion.PatchSuffix = std::string(PatchText.substr(EndNumber));
}
}
@@ -1848,7 +1899,7 @@ void Generic_GCC::GCCInstallationDetector::init(
if (GCCToolchainDir.back() == '/')
GCCToolchainDir = GCCToolchainDir.drop_back(); // remove the /
- Prefixes.push_back(GCCToolchainDir);
+ Prefixes.push_back(std::string(GCCToolchainDir));
} else {
// If we have a SysRoot, try that first.
if (!D.SysRoot.empty()) {
@@ -1975,6 +2026,7 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
// Non-Solaris is much simpler - most systems just go with "/usr".
if (SysRoot.empty() && TargetTriple.getOS() == llvm::Triple::Linux) {
// Yet, still look for RHEL devtoolsets.
+ Prefixes.push_back("/opt/rh/devtoolset-9/root/usr");
Prefixes.push_back("/opt/rh/devtoolset-8/root/usr");
Prefixes.push_back("/opt/rh/devtoolset-7/root/usr");
Prefixes.push_back("/opt/rh/devtoolset-6/root/usr");
@@ -2090,6 +2142,7 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
static const char *const RISCV64Triples[] = {"riscv64-unknown-linux-gnu",
"riscv64-linux-gnu",
"riscv64-unknown-elf",
+ "riscv64-redhat-linux",
"riscv64-suse-linux"};
static const char *const SPARCv8LibDirs[] = {"/lib32", "/lib"};
@@ -2460,7 +2513,7 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
StringRef VersionText = llvm::sys::path::filename(LI->path());
GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);
if (CandidateVersion.Major != -1) // Filter obviously bad entries.
- if (!CandidateGCCInstallPaths.insert(LI->path()).second)
+ if (!CandidateGCCInstallPaths.insert(std::string(LI->path())).second)
continue; // Saw this path before; no need to look at it again.
if (CandidateVersion.isOlderThan(4, 1, 1))
continue;
@@ -2572,7 +2625,7 @@ bool Generic_GCC::GCCInstallationDetector::ScanGentooGccConfig(
Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args), GCCInstallation(D),
- CudaInstallation(D, Triple, Args) {
+ CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
@@ -2605,6 +2658,7 @@ 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);
}
bool Generic_GCC::IsUnwindTablesDefault(const ArgList &Args) const {
@@ -2666,6 +2720,140 @@ bool Generic_GCC::IsIntegratedAssemblerDefault() const {
}
}
+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);
+}
+
+void Generic_GCC::PushPPaths(ToolChain::path_list &PPaths) {
+ // Cross-compiling binutils and GCC installations (vanilla and openSUSE at
+ // least) put various tools in a triple-prefixed directory off of the parent
+ // of the GCC installation. We use the GCC triple here to ensure that we end
+ // up with tools that support the same amount of cross compiling as the
+ // detected GCC installation. For example, if we find a GCC installation
+ // targeting x86_64, but it is a bi-arch GCC installation, it can also be
+ // used to target i386.
+ if (GCCInstallation.isValid()) {
+ PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +
+ GCCInstallation.getTriple().str() + "/bin")
+ .str());
+ }
+}
+
+void Generic_GCC::AddMultilibPaths(const Driver &D,
+ const std::string &SysRoot,
+ const std::string &OSLibDir,
+ const std::string &MultiarchTriple,
+ path_list &Paths) {
+ // Add the multilib suffixed paths where they are available.
+ if (GCCInstallation.isValid()) {
+ const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
+ const std::string &LibPath =
+ std::string(GCCInstallation.getParentLibPath());
+
+ // Add toolchain / multilib specific file paths.
+ addMultilibsFilePaths(D, Multilibs, SelectedMultilib,
+ GCCInstallation.getInstallPath(), Paths);
+
+ // Sourcery CodeBench MIPS toolchain holds some libraries under
+ // a biarch-like suffix of the GCC installation.
+ addPathIfExists(
+ D, GCCInstallation.getInstallPath() + SelectedMultilib.gccSuffix(),
+ Paths);
+
+ // GCC cross compiling toolchains will install target libraries which ship
+ // as part of the toolchain under <prefix>/<triple>/<libdir> rather than as
+ // any part of the GCC installation in
+ // <prefix>/<libdir>/gcc/<triple>/<version>. This decision is somewhat
+ // debatable, but is the reality today. We need to search this tree even
+ // when we have a sysroot somewhere else. It is the responsibility of
+ // whomever is doing the cross build targeting a sysroot using a GCC
+ // installation that is *not* within the system root to ensure two things:
+ //
+ // 1) Any DSOs that are linked in from this tree or from the install path
+ // above must be present on the system root and found via an
+ // appropriate rpath.
+ // 2) There must not be libraries installed into
+ // <prefix>/<triple>/<libdir> unless they should be preferred over
+ // those within the system root.
+ //
+ // Note that this matches the GCC behavior. See the below comment for where
+ // Clang diverges from GCC's behavior.
+ addPathIfExists(D,
+ LibPath + "/../" + GCCTriple.str() + "/lib/../" + OSLibDir +
+ SelectedMultilib.osSuffix(),
+ Paths);
+
+ // If the GCC installation we found is inside of the sysroot, we want to
+ // prefer libraries installed in the parent prefix of the GCC installation.
+ // It is important to *not* use these paths when the GCC installation is
+ // outside of the system root as that can pick up unintended libraries.
+ // This usually happens when there is an external cross compiler on the
+ // host system, and a more minimal sysroot available that is the target of
+ // 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)) {
+ addPathIfExists(D, LibPath + "/" + MultiarchTriple, Paths);
+ addPathIfExists(D, LibPath + "/../" + OSLibDir, Paths);
+ }
+ }
+}
+
+void Generic_GCC::AddMultiarchPaths(const Driver &D,
+ const std::string &SysRoot,
+ const std::string &OSLibDir,
+ path_list &Paths) {
+ // Try walking via the GCC triple path in case of biarch or multiarch GCC
+ // installations with strange symlinks.
+ if (GCCInstallation.isValid()) {
+ addPathIfExists(D,
+ SysRoot + "/usr/lib/" + GCCInstallation.getTriple().str() +
+ "/../../" + OSLibDir,
+ Paths);
+
+ // Add the 'other' biarch variant path
+ Multilib BiarchSibling;
+ if (GCCInstallation.getBiarchSibling(BiarchSibling)) {
+ addPathIfExists(
+ D, GCCInstallation.getInstallPath() + BiarchSibling.gccSuffix(),
+ Paths);
+ }
+
+ // See comments above on the multilib variant for details of why this is
+ // included even from outside the sysroot.
+ const std::string &LibPath =
+ std::string(GCCInstallation.getParentLibPath());
+ const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
+ const Multilib &Multilib = GCCInstallation.getMultilib();
+ addPathIfExists(
+ D, LibPath + "/../" + GCCTriple.str() + "/lib" + Multilib.osSuffix(),
+ Paths);
+
+ // See comments above on the multilib variant for details of why this is
+ // only included from within the sysroot.
+ if (StringRef(LibPath).startswith(SysRoot))
+ addPathIfExists(D, LibPath, Paths);
+ }
+}
+
+void Generic_GCC::AddMultilibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ // Add include directories specific to the selected multilib set and multilib.
+ if (GCCInstallation.isValid()) {
+ const auto &Callback = Multilibs.includeDirsCallback();
+ if (Callback) {
+ for (const auto &Path : Callback(GCCInstallation.getMultilib()))
+ addExternCSystemIncludeIfExists(
+ DriverArgs, CC1Args, GCCInstallation.getInstallPath() + Path);
+ }
+ }
+}
+
void Generic_GCC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
@@ -2696,7 +2884,7 @@ static std::string DetectLibcxxIncludePath(llvm::vfs::FileSystem &vfs,
!VersionText.slice(1, StringRef::npos).getAsInteger(10, Version)) {
if (Version > MaxVersion) {
MaxVersion = Version;
- MaxVersionString = VersionText;
+ MaxVersionString = std::string(VersionText);
}
}
}
@@ -2706,7 +2894,6 @@ static std::string DetectLibcxxIncludePath(llvm::vfs::FileSystem &vfs,
void
Generic_GCC::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
- const std::string& SysRoot = getDriver().SysRoot;
auto AddIncludePath = [&](std::string Path) {
std::string IncludePath = DetectLibcxxIncludePath(getVFS(), Path);
if (IncludePath.empty() || !getVFS().exists(IncludePath))
@@ -2722,6 +2909,7 @@ Generic_GCC::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
// If this is a development, non-installed, clang, libcxx will
// not be found at ../include/c++ but it likely to be found at
// one of the following two locations:
+ std::string SysRoot = computeSysRoot();
if (AddIncludePath(SysRoot + "/usr/local/include/c++"))
return;
if (AddIncludePath(SysRoot + "/usr/include/c++"))
diff --git a/clang/lib/Driver/ToolChains/Gnu.h b/clang/lib/Driver/ToolChains/Gnu.h
index 083f74c054774..52690ab4b83c2 100644
--- a/clang/lib/Driver/ToolChains/Gnu.h
+++ b/clang/lib/Driver/ToolChains/Gnu.h
@@ -10,6 +10,7 @@
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_GNU_H
#include "Cuda.h"
+#include "ROCm.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
#include <set>
@@ -35,23 +36,26 @@ bool findMIPSMultilibs(const Driver &D, const llvm::Triple &TargetTriple,
namespace tools {
-/// Base class for all GNU tools that provide the same behavior when
-/// it comes to response files support
-class LLVM_LIBRARY_VISIBILITY GnuTool : public Tool {
- virtual void anchor();
-
+/// Directly call GNU Binutils' assembler and linker.
+namespace gnutools {
+class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
public:
- GnuTool(const char *Name, const char *ShortName, const ToolChain &TC)
- : Tool(Name, ShortName, TC, RF_Full, llvm::sys::WEM_CurrentCodePage) {}
+ Assembler(const ToolChain &TC) : Tool("GNU::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;
};
-/// Directly call GNU Binutils' assembler and linker.
-namespace gnutools {
-class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
- Assembler(const ToolChain &TC) : GnuTool("GNU::Assembler", "assembler", TC) {}
+ Linker(const ToolChain &TC) : Tool("GNU::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,
@@ -59,9 +63,10 @@ public:
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY StaticLibTool : public Tool {
public:
- Linker(const ToolChain &TC) : GnuTool("GNU::Linker", "linker", TC) {}
+ StaticLibTool(const ToolChain &TC)
+ : Tool("GNU::StaticLibTool", "static-lib-linker", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
@@ -75,10 +80,10 @@ public:
/// gcc - Generic GCC tool implementations.
namespace gcc {
-class LLVM_LIBRARY_VISIBILITY Common : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Common : public Tool {
public:
Common(const char *Name, const char *ShortName, const ToolChain &TC)
- : GnuTool(Name, ShortName, TC) {}
+ : Tool(Name, ShortName, TC) {}
// A gcc tool has an "integrated" assembler that it will call to produce an
// object. Let it use that assembler so that we don't have to deal with
@@ -278,6 +283,7 @@ public:
protected:
GCCInstallationDetector GCCInstallation;
CudaInstallationDetector CudaInstallation;
+ RocmInstallationDetector RocmInstallation;
public:
Generic_GCC(const Driver &D, const llvm::Triple &Triple,
@@ -314,6 +320,16 @@ protected:
/// Check whether the target triple's architecture is 32-bits.
bool isTarget32Bit() const { return getTriple().isArch32Bit(); }
+ void PushPPaths(ToolChain::path_list &PPaths);
+ void AddMultilibPaths(const Driver &D, const std::string &SysRoot,
+ const std::string &OSLibDir,
+ const std::string &MultiarchTriple,
+ path_list &Paths);
+ void AddMultiarchPaths(const Driver &D, const std::string &SysRoot,
+ const std::string &OSLibDir, path_list &Paths);
+ void AddMultilibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+
// FIXME: This should be final, but the CrossWindows toolchain does weird
// things that can't be easily generalized.
void AddClangCXXStdlibIncludeArgs(
@@ -356,6 +372,12 @@ public:
void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadKind) const override;
+
+ virtual std::string getDynamicLinker(const llvm::opt::ArgList &Args) const {
+ return {};
+ }
+
+ virtual void addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const {}
};
} // end namespace toolchains
diff --git a/clang/lib/Driver/ToolChains/HIP.cpp b/clang/lib/Driver/ToolChains/HIP.cpp
index f89e648948aba..7d17f809690ea 100644
--- a/clang/lib/Driver/ToolChains/HIP.cpp
+++ b/clang/lib/Driver/ToolChains/HIP.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "HIP.h"
+#include "AMDGPU.h"
#include "CommonArgs.h"
#include "InputInfo.h"
#include "clang/Basic/Cuda.h"
@@ -16,6 +17,7 @@
#include "clang/Driver/Options.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;
@@ -47,159 +49,51 @@ static void addBCLib(const Driver &D, const ArgList &Args,
}
D.Diag(diag::err_drv_no_such_file) << BCName;
}
-
-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 addOptLevelArgs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs,
- bool IsLlc = false) {
- if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
- StringRef OOpt = "3";
- 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", IsLlc ? "2" : "s")
- .Case("z", IsLlc ? "2" : "z")
- .Case("g", "1")
- .Default("2");
- }
- CmdArgs.push_back(Args.MakeArgString("-O" + OOpt));
- }
-}
} // namespace
-const char *AMDGCN::Linker::constructLLVMLinkCommand(
- Compilation &C, const JobAction &JA, const InputInfoList &Inputs,
- const ArgList &Args, StringRef SubArchName,
- StringRef OutputFilePrefix) const {
- ArgStringList CmdArgs;
- // Add the input bc's created by compile step.
- for (const auto &II : Inputs)
- CmdArgs.push_back(II.getFilename());
-
- // Add an intermediate output file.
- CmdArgs.push_back("-o");
- auto OutputFileName = getOutputFileName(C, OutputFilePrefix, "-linked", "bc");
- CmdArgs.push_back(OutputFileName);
- SmallString<128> ExecPath(C.getDriver().Dir);
- llvm::sys::path::append(ExecPath, "llvm-link");
- const char *Exec = Args.MakeArgString(ExecPath);
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
- return OutputFileName;
-}
-
-const char *AMDGCN::Linker::constructOptCommand(
- Compilation &C, const JobAction &JA, const InputInfoList &Inputs,
- const llvm::opt::ArgList &Args, llvm::StringRef SubArchName,
- llvm::StringRef OutputFilePrefix, const char *InputFileName) const {
- // Construct opt command.
- ArgStringList OptArgs;
- // The input to opt is the output from llvm-link.
- OptArgs.push_back(InputFileName);
- // Pass optimization arg to opt.
- addOptLevelArgs(Args, OptArgs);
- OptArgs.push_back("-mtriple=amdgcn-amd-amdhsa");
- OptArgs.push_back(Args.MakeArgString("-mcpu=" + SubArchName));
-
- for (const Arg *A : Args.filtered(options::OPT_mllvm)) {
- OptArgs.push_back(A->getValue(0));
- }
-
- OptArgs.push_back("-o");
- auto OutputFileName =
- getOutputFileName(C, OutputFilePrefix, "-optimized", "bc");
- OptArgs.push_back(OutputFileName);
- SmallString<128> OptPath(C.getDriver().Dir);
- llvm::sys::path::append(OptPath, "opt");
- const char *OptExec = Args.MakeArgString(OptPath);
- C.addCommand(std::make_unique<Command>(JA, *this, OptExec, OptArgs, Inputs));
- return OutputFileName;
-}
+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"};
-const char *AMDGCN::Linker::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.
- addOptLevelArgs(Args, LlcArgs, /*IsLlc=*/true);
- LlcArgs.push_back("-mtriple=amdgcn-amd-amdhsa");
- LlcArgs.push_back(Args.MakeArgString("-mcpu=" + SubArchName));
- LlcArgs.push_back(
- Args.MakeArgString(Twine("-filetype=") + (OutputIsAsm ? "asm" : "obj")));
+ auto &TC = getToolChain();
+ auto &D = TC.getDriver();
+ assert(!Inputs.empty() && "Must have at least one input.");
+ addLTOOptions(TC, Args, LldArgs, Output, Inputs[0],
+ D.getLTOMode() == LTOK_Thin);
// Extract all the -m options
std::vector<llvm::StringRef> Features;
- handleTargetFeaturesGroup(
- Args, Features, options::OPT_m_amdgpu_Features_Group);
+ amdgpu::getAMDGPUTargetFeatures(D, Args, Features);
- // Add features to mattr such as xnack
- std::string MAttrString = "-mattr=";
- for(auto OneFeature : 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())
- LlcArgs.push_back(Args.MakeArgString(MAttrString));
+ if (!Features.empty())
+ LldArgs.push_back(Args.MakeArgString(MAttrString));
for (const Arg *A : Args.filtered(options::OPT_mllvm)) {
- LlcArgs.push_back(A->getValue(0));
+ LldArgs.push_back(
+ Args.MakeArgString(Twine("-plugin-opt=") + A->getValue(0)));
}
- // Add output filename
- LlcArgs.push_back("-o");
- auto LlcOutputFile =
- getOutputFileName(C, OutputFilePrefix, "", OutputIsAsm ? "s" : "o");
- LlcArgs.push_back(LlcOutputFile);
- SmallString<128> LlcPath(C.getDriver().Dir);
- llvm::sys::path::append(LlcPath, "llc");
- const char *Llc = Args.MakeArgString(LlcPath);
- C.addCommand(std::make_unique<Command>(JA, *this, Llc, LlcArgs, Inputs));
- return LlcOutputFile;
-}
-
-void AMDGCN::Linker::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", "-shared", "-o", Output.getFilename(), InputFileName};
- SmallString<128> LldPath(C.getDriver().Dir);
- llvm::sys::path::append(LldPath, "lld");
- const char *Lld = Args.MakeArgString(LldPath);
- C.addCommand(std::make_unique<Command>(JA, *this, Lld, LldArgs, Inputs));
+ if (C.getDriver().isSaveTempsEnabled())
+ LldArgs.push_back("-save-temps");
+
+ LldArgs.append({"-o", Output.getFilename()});
+ for (auto Input : Inputs)
+ LldArgs.push_back(Input.getFilename());
+ const char *Lld = Args.MakeArgString(getToolChain().GetProgramPath("lld"));
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Lld, LldArgs, Inputs));
}
// Construct a clang-offload-bundler command to bundle code objects for
@@ -226,14 +120,84 @@ void AMDGCN::constructHIPFatbinCommand(Compilation &C, const JobAction &JA,
BundlerArgs.push_back(Args.MakeArgString(BundlerTargetArg));
BundlerArgs.push_back(Args.MakeArgString(BundlerInputArg));
- auto BundlerOutputArg =
- Args.MakeArgString(std::string("-outputs=").append(OutputFileName));
+ auto BundlerOutputArg = Args.MakeArgString(
+ std::string("-outputs=").append(std::string(OutputFileName)));
BundlerArgs.push_back(BundlerOutputArg);
- SmallString<128> BundlerPath(C.getDriver().Dir);
- llvm::sys::path::append(BundlerPath, "clang-offload-bundler");
- const char *Bundler = Args.MakeArgString(BundlerPath);
- C.addCommand(std::make_unique<Command>(JA, T, Bundler, BundlerArgs, Inputs));
+ const char *Bundler = Args.MakeArgString(
+ T.getToolChain().GetProgramPath("clang-offload-bundler"));
+ C.addCommand(std::make_unique<Command>(JA, T, ResponseFileSupport::None(),
+ Bundler, BundlerArgs, Inputs));
+}
+
+/// 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 << " .type __hip_fatbin,@object\n";
+ ObjStream << " .section .hip_fatbin,\"aMS\",@progbits,1\n";
+ ObjStream << " .data\n";
+ ObjStream << " .globl __hip_fatbin\n";
+ ObjStream << " .p2align 3\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));
}
// For amdgcn the inputs of the linker job are device bitcode and output is
@@ -243,37 +207,20 @@ void AMDGCN::Linker::ConstructJob(Compilation &C, const JobAction &JA,
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);
- assert(getToolChain().getTriple().getArch() == llvm::Triple::amdgcn &&
- "Unsupported target");
-
- std::string SubArchName = JA.getOffloadingArch();
- assert(StringRef(SubArchName).startswith("gfx") && "Unsupported sub arch");
-
- // Prefix for temporary file name.
- std::string Prefix = llvm::sys::path::stem(Inputs[0].getFilename()).str();
- if (!C.getDriver().isSaveTempsEnabled())
- Prefix += "-" + SubArchName;
-
- // Each command outputs different files.
- const char *LLVMLinkCommand =
- constructLLVMLinkCommand(C, JA, Inputs, Args, SubArchName, Prefix);
- const char *OptCommand = constructOptCommand(C, JA, Inputs, Args, SubArchName,
- Prefix, LLVMLinkCommand);
- if (C.getDriver().isSaveTempsEnabled())
- constructLlcCommand(C, JA, Inputs, Args, SubArchName, Prefix, OptCommand,
- /*OutputIsAsm=*/true);
- const char *LlcCommand =
- constructLlcCommand(C, JA, Inputs, Args, SubArchName, Prefix, OptCommand);
- constructLldCommand(C, JA, Inputs, Output, Args, LlcCommand);
+ return constructLldCommand(C, JA, Inputs, Output, Args);
}
HIPToolChain::HIPToolChain(const Driver &D, const llvm::Triple &Triple,
const ToolChain &HostTC, const ArgList &Args)
- : ToolChain(D, Triple, Args), HostTC(HostTC) {
+ : 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);
@@ -285,20 +232,16 @@ void HIPToolChain::addClangTargetOptions(
Action::OffloadKind DeviceOffloadingKind) const {
HostTC.addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadingKind);
- StringRef GpuArch = DriverArgs.getLastArgValue(options::OPT_march_EQ);
+ StringRef GpuArch = DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
assert(!GpuArch.empty() && "Must have an explicit GPU arch.");
(void) GpuArch;
assert(DeviceOffloadingKind == Action::OFK_HIP &&
"Only HIP offloading kinds are supported for GPUs.");
+ auto Kind = llvm::AMDGPU::parseArchAMDGCN(GpuArch);
+ const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind);
- CC1Args.push_back("-target-cpu");
- CC1Args.push_back(DriverArgs.MakeArgStringRef(GpuArch));
CC1Args.push_back("-fcuda-is-device");
- if (DriverArgs.hasFlag(options::OPT_fcuda_flush_denormals_to_zero,
- options::OPT_fno_cuda_flush_denormals_to_zero, false))
- CC1Args.push_back("-fcuda-flush-denormals-to-zero");
-
if (DriverArgs.hasFlag(options::OPT_fcuda_approx_transcendentals,
options::OPT_fno_cuda_approx_transcendentals, false))
CC1Args.push_back("-fcuda-approx-transcendentals");
@@ -306,6 +249,8 @@ void HIPToolChain::addClangTargetOptions(
if (DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
false))
CC1Args.push_back("-fgpu-rdc");
+ else
+ CC1Args.append({"-mllvm", "-amdgpu-internalize-symbols"});
StringRef MaxThreadsPerBlock =
DriverArgs.getLastArgValue(options::OPT_gpu_max_threads_per_block_EQ);
@@ -334,46 +279,50 @@ void HIPToolChain::addClangTargetOptions(
ArgStringList LibraryPaths;
// Find in --hip-device-lib-path and HIP_LIBRARY_PATH.
- for (auto Path :
- DriverArgs.getAllArgValues(options::OPT_hip_device_lib_path_EQ))
+ for (auto Path : RocmInstallation.getRocmDeviceLibPathArg())
LibraryPaths.push_back(DriverArgs.MakeArgString(Path));
- addDirectoryList(DriverArgs, LibraryPaths, "-L", "HIP_DEVICE_LIB_PATH");
+ addDirectoryList(DriverArgs, LibraryPaths, "", "HIP_DEVICE_LIB_PATH");
- llvm::SmallVector<std::string, 10> BCLibs;
+ // Maintain compatability with --hip-device-lib.
+ auto BCLibs = DriverArgs.getAllArgValues(options::OPT_hip_device_lib_EQ);
+ if (!BCLibs.empty()) {
+ for (auto Lib : BCLibs)
+ addBCLib(getDriver(), DriverArgs, CC1Args, LibraryPaths, Lib);
+ } else {
+ if (!RocmInstallation.hasDeviceLibrary()) {
+ getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 0;
+ return;
+ }
- // Add bitcode library in --hip-device-lib.
- for (auto Lib : DriverArgs.getAllArgValues(options::OPT_hip_device_lib_EQ)) {
- BCLibs.push_back(DriverArgs.MakeArgString(Lib));
- }
+ std::string LibDeviceFile = RocmInstallation.getLibDeviceFile(CanonArch);
+ if (LibDeviceFile.empty()) {
+ getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 1 << GpuArch;
+ return;
+ }
- // If --hip-device-lib is not set, add the default bitcode libraries.
- if (BCLibs.empty()) {
- // Get the bc lib file name for ISA version. For example,
- // gfx803 => oclc_isa_version_803.amdgcn.bc.
- std::string GFXVersion = GpuArch.drop_front(3).str();
- std::string ISAVerBC = "oclc_isa_version_" + GFXVersion + ".amdgcn.bc";
-
- llvm::StringRef FlushDenormalControlBC;
- if (DriverArgs.hasArg(options::OPT_fcuda_flush_denormals_to_zero))
- FlushDenormalControlBC = "oclc_daz_opt_on.amdgcn.bc";
- else
- FlushDenormalControlBC = "oclc_daz_opt_off.amdgcn.bc";
-
- llvm::StringRef WaveFrontSizeBC;
- if (stoi(GFXVersion) < 1000)
- WaveFrontSizeBC = "oclc_wavefrontsize64_on.amdgcn.bc";
- else
- WaveFrontSizeBC = "oclc_wavefrontsize64_off.amdgcn.bc";
-
- BCLibs.append({"hip.amdgcn.bc", "ocml.amdgcn.bc", "ockl.amdgcn.bc",
- "oclc_finite_only_off.amdgcn.bc", FlushDenormalControlBC,
- "oclc_correctly_rounded_sqrt_on.amdgcn.bc",
- "oclc_unsafe_math_off.amdgcn.bc", ISAVerBC,
- WaveFrontSizeBC});
+ // If --hip-device-lib is not set, add the default bitcode libraries.
+ // TODO: There are way too many flags that change this. Do we need to check
+ // them all?
+ bool DAZ = DriverArgs.hasFlag(options::OPT_fcuda_flush_denormals_to_zero,
+ options::OPT_fno_cuda_flush_denormals_to_zero,
+ getDefaultDenormsAreZeroForTarget(Kind));
+ // TODO: Check standard C++ flags?
+ bool FiniteOnly = false;
+ bool UnsafeMathOpt = false;
+ bool FastRelaxedMath = false;
+ bool CorrectSqrt = true;
+ bool Wave64 = isWave64(DriverArgs, Kind);
+
+ // Add the HIP specific bitcode library.
+ CC1Args.push_back("-mlink-builtin-bitcode");
+ CC1Args.push_back(DriverArgs.MakeArgString(RocmInstallation.getHIPPath()));
+
+ // Add the generic set of libraries.
+ RocmInstallation.addCommonBitcodeLibCC1Args(
+ DriverArgs, CC1Args, LibDeviceFile, Wave64, DAZ, FiniteOnly,
+ UnsafeMathOpt, FastRelaxedMath, CorrectSqrt);
}
- for (auto Lib : BCLibs)
- addBCLib(getDriver(), DriverArgs, CC1Args, LibraryPaths, Lib);
}
llvm::opt::DerivedArgList *
@@ -388,42 +337,12 @@ HIPToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
const OptTable &Opts = getDriver().getOpts();
for (Arg *A : Args) {
- if (A->getOption().matches(options::OPT_Xarch__)) {
- // Skip this argument unless the architecture matches BoundArch.
- if (BoundArch.empty() || A->getValue(0) != BoundArch)
- continue;
-
- unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
- unsigned Prev = Index;
- std::unique_ptr<Arg> XarchArg(Opts.ParseOneArg(Args, Index));
-
- // If the argument parsing failed or more than one argument was
- // consumed, the -Xarch_ argument's parameter tried to consume
- // extra arguments. Emit an error and ignore.
- //
- // We also want to disallow any options which would alter the
- // driver behavior; that isn't going to work in our model. We
- // use isDriverOption() as an approximation, although things
- // like -O4 are going to slip through.
- if (!XarchArg || Index > Prev + 1) {
- getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args)
- << A->getAsString(Args);
- continue;
- } else if (XarchArg->getOption().hasFlag(options::DriverOption)) {
- getDriver().Diag(diag::err_drv_invalid_Xarch_argument_isdriver)
- << A->getAsString(Args);
- continue;
- }
- XarchArg->setBaseArg(A);
- A = XarchArg.release();
- DAL->AddSynthesizedArg(A);
- }
DAL->append(A);
}
if (!BoundArch.empty()) {
- DAL->eraseArg(options::OPT_march_EQ);
- DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), BoundArch);
+ DAL->eraseArg(options::OPT_mcpu_EQ);
+ DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_mcpu_EQ), BoundArch);
}
return DAL;
@@ -458,6 +377,11 @@ void HIPToolChain::AddIAMCUIncludeArgs(const ArgList &Args,
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
diff --git a/clang/lib/Driver/ToolChains/HIP.h b/clang/lib/Driver/ToolChains/HIP.h
index c4f944e458bf2..5e2be7138579a 100644
--- a/clang/lib/Driver/ToolChains/HIP.h
+++ b/clang/lib/Driver/ToolChains/HIP.h
@@ -11,6 +11,7 @@
#include "clang/Driver/ToolChain.h"
#include "clang/Driver/Tool.h"
+#include "AMDGPU.h"
namespace clang {
namespace driver {
@@ -37,34 +38,17 @@ public:
const char *LinkingOutput) const override;
private:
- /// \return llvm-link output file name.
- const char *constructLLVMLinkCommand(Compilation &C, const JobAction &JA,
- const InputInfoList &Inputs,
- const llvm::opt::ArgList &Args,
- llvm::StringRef SubArchName,
- llvm::StringRef OutputFilePrefix) const;
-
- /// \return opt output file name.
- const char *constructOptCommand(Compilation &C, const JobAction &JA,
- const InputInfoList &Inputs,
- const llvm::opt::ArgList &Args,
- llvm::StringRef SubArchName,
- llvm::StringRef OutputFilePrefix,
- const char *InputFileName) 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;
+ 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;
};
} // end namespace AMDGCN
@@ -72,7 +56,7 @@ private:
namespace toolchains {
-class LLVM_LIBRARY_VISIBILITY HIPToolChain : public ToolChain {
+class LLVM_LIBRARY_VISIBILITY HIPToolChain final : public ROCMToolChain {
public:
HIPToolChain(const Driver &D, const llvm::Triple &Triple,
const ToolChain &HostTC, const llvm::opt::ArgList &Args);
@@ -106,6 +90,8 @@ public:
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;
SanitizerMask getSupportedSanitizers() const override;
diff --git a/clang/lib/Driver/ToolChains/Hexagon.cpp b/clang/lib/Driver/ToolChains/Hexagon.cpp
index e4d9ea8a70f9e..775f6e1094fa6 100644
--- a/clang/lib/Driver/ToolChains/Hexagon.cpp
+++ b/clang/lib/Driver/ToolChains/Hexagon.cpp
@@ -31,7 +31,6 @@ static StringRef getDefaultHvxLength(StringRef Cpu) {
.Case("v60", "64b")
.Case("v62", "64b")
.Case("v65", "64b")
- .Case("v66", "128b")
.Default("128b");
}
@@ -48,13 +47,12 @@ static void handleHVXWarnings(const Driver &D, const ArgList &Args) {
// Handle hvx target features explicitly.
static void handleHVXTargetFeatures(const Driver &D, const ArgList &Args,
std::vector<StringRef> &Features,
- bool &HasHVX) {
+ StringRef Cpu, bool &HasHVX) {
// Handle HVX warnings.
handleHVXWarnings(D, Args);
// Add the +hvx* features based on commandline flags.
StringRef HVXFeature, HVXLength;
- StringRef Cpu(toolchains::HexagonToolChain::GetTargetCPUVersion(Args));
// Handle -mhvx, -mhvx=, -mno-hvx.
if (Arg *A = Args.getLastArg(options::OPT_mno_hexagon_hvx,
@@ -108,7 +106,15 @@ void hexagon::getHexagonTargetFeatures(const Driver &D, const ArgList &Args,
Features.push_back(UseLongCalls ? "+long-calls" : "-long-calls");
bool HasHVX = false;
- handleHVXTargetFeatures(D, Args, Features, HasHVX);
+ StringRef Cpu(toolchains::HexagonToolChain::GetTargetCPUVersion(Args));
+ // 't' in Cpu denotes tiny-core micro-architecture. For now, the co-processors
+ // have no dependency on micro-architecture.
+ const bool TinyCore = Cpu.contains('t');
+
+ if (TinyCore)
+ Cpu = Cpu.take_front(Cpu.size() - 1);
+
+ handleHVXTargetFeatures(D, Args, Features, Cpu, HasHVX);
if (HexagonToolChain::isAutoHVXEnabled(Args) && !HasHVX)
D.Diag(diag::warn_drv_vectorize_needs_hvx);
@@ -183,7 +189,8 @@ void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
}
auto *Exec = Args.MakeArgString(HTC.GetProgramPath(AsName));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
}
void hexagon::Linker::RenderExtraToolArgs(const JobAction &JA,
@@ -258,18 +265,43 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
UseG0 = G.getValue() == 0;
}
- //----------------------------------------------------------------------------
- //
- //----------------------------------------------------------------------------
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
+ if (HTC.getTriple().isMusl()) {
+ if (!Args.hasArg(options::OPT_shared, options::OPT_static))
+ CmdArgs.push_back("-dynamic-linker=/lib/ld-musl-hexagon.so.1");
+
+ if (!Args.hasArg(options::OPT_shared, options::OPT_nostartfiles,
+ options::OPT_nostdlib))
+ CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crt1.o"));
+ else if (Args.hasArg(options::OPT_shared) &&
+ !Args.hasArg(options::OPT_nostartfiles, options::OPT_nostdlib))
+ CmdArgs.push_back(Args.MakeArgString(D.SysRoot + "/usr/lib/crti.o"));
+
+ 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});
+ AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
+
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ CmdArgs.push_back("-lclang_rt.builtins-hexagon");
+ CmdArgs.push_back("-lc");
+ }
+ if (D.CCCIsCXX()) {
+ if (HTC.ShouldLinkCXXStdlib(Args))
+ HTC.AddCXXStdlibLibArgs(Args, CmdArgs);
+ }
+ return;
+ }
+
//----------------------------------------------------------------------------
// moslib
//----------------------------------------------------------------------------
std::vector<std::string> OsLibs;
bool HasStandalone = false;
-
for (const Arg *A : Args.filtered(options::OPT_moslib_EQ)) {
A->claim();
OsLibs.emplace_back(A->getValue());
@@ -375,7 +407,8 @@ void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA,
LinkingOutput);
const char *Exec = Args.MakeArgString(HTC.GetLinkerPath());
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
}
// Hexagon tools end.
@@ -481,6 +514,22 @@ HexagonToolChain::HexagonToolChain(const Driver &D, const llvm::Triple &Triple,
HexagonToolChain::~HexagonToolChain() {}
+void HexagonToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ CXXStdlibType Type = GetCXXStdlibType(Args);
+ switch (Type) {
+ case ToolChain::CST_Libcxx:
+ CmdArgs.push_back("-lc++");
+ CmdArgs.push_back("-lc++abi");
+ CmdArgs.push_back("-lunwind");
+ break;
+
+ case ToolChain::CST_Libstdcxx:
+ CmdArgs.push_back("-lstdc++");
+ break;
+ }
+}
+
Tool *HexagonToolChain::buildAssembler() const {
return new tools::hexagon::Assembler(*this);
}
@@ -517,6 +566,14 @@ unsigned HexagonToolChain::getOptimizationLevel(
void HexagonToolChain::addClangTargetOptions(const ArgList &DriverArgs,
ArgStringList &CC1Args,
Action::OffloadKind) const {
+
+ bool UseInitArrayDefault = getTriple().isMusl();
+
+ if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
+ options::OPT_fno_use_init_array,
+ UseInitArrayDefault))
+ CC1Args.push_back("-fno-use-init-array");
+
if (DriverArgs.hasArg(options::OPT_ffixed_r19)) {
CC1Args.push_back("-target-feature");
CC1Args.push_back("+reserved-r19");
@@ -534,12 +591,37 @@ void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
return;
const Driver &D = getDriver();
+ if (!D.SysRoot.empty()) {
+ SmallString<128> P(D.SysRoot);
+ if (getTriple().isMusl())
+ llvm::sys::path::append(P, "usr/include");
+ else
+ llvm::sys::path::append(P, "include");
+ addExternCSystemInclude(DriverArgs, CC1Args, P.str());
+ return;
+ }
+
std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
D.PrefixDirs);
addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include");
}
-
+void HexagonToolChain::addLibCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ const Driver &D = getDriver();
+ if (!D.SysRoot.empty() && getTriple().isMusl())
+ addLibStdCXXIncludePaths(D.SysRoot + "/usr/include/c++/v1", "", "", "", "",
+ "", DriverArgs, CC1Args);
+ else if (getTriple().isMusl())
+ addLibStdCXXIncludePaths("/usr/include/c++/v1", "", "", "", "", "",
+ DriverArgs, CC1Args);
+ else {
+ std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs);
+ addLibStdCXXIncludePaths(TargetDir, "/hexagon/include/c++/v1", "", "", "",
+ "", DriverArgs, CC1Args);
+ }
+}
void HexagonToolChain::addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
@@ -552,14 +634,22 @@ void HexagonToolChain::addLibStdCxxIncludePaths(
ToolChain::CXXStdlibType
HexagonToolChain::GetCXXStdlibType(const ArgList &Args) const {
Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
- if (!A)
- return ToolChain::CST_Libstdcxx;
-
+ if (!A) {
+ if (getTriple().isMusl())
+ return ToolChain::CST_Libcxx;
+ else
+ return ToolChain::CST_Libstdcxx;
+ }
StringRef Value = A->getValue();
- if (Value != "libstdc++")
+ if (Value != "libstdc++" && Value != "libc++")
getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args);
- return ToolChain::CST_Libstdcxx;
+ if (Value == "libstdc++")
+ return ToolChain::CST_Libstdcxx;
+ else if (Value == "libc++")
+ return ToolChain::CST_Libcxx;
+ else
+ return ToolChain::CST_Libstdcxx;
}
bool HexagonToolChain::isAutoHVXEnabled(const llvm::opt::ArgList &Args) {
diff --git a/clang/lib/Driver/ToolChains/Hexagon.h b/clang/lib/Driver/ToolChains/Hexagon.h
index d7b4a13d3a4f8..c32cb7f09591a 100644
--- a/clang/lib/Driver/ToolChains/Hexagon.h
+++ b/clang/lib/Driver/ToolChains/Hexagon.h
@@ -20,10 +20,10 @@ 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 GnuTool {
+class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
public:
Assembler(const ToolChain &TC)
- : GnuTool("hexagon::Assembler", "hexagon-as", TC) {}
+ : Tool("hexagon::Assembler", "hexagon-as", TC) {}
bool hasIntegratedCPP() const override { return false; }
@@ -35,9 +35,9 @@ public:
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
- Linker(const ToolChain &TC) : GnuTool("hexagon::Linker", "hexagon-ld", TC) {}
+ Linker(const ToolChain &TC) : Tool("hexagon::Linker", "hexagon-ld", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
@@ -81,10 +81,18 @@ public:
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- const char *getDefaultLinker() const override { return "hexagon-link"; }
+ void addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
+ const char *getDefaultLinker() const override {
+ return getTriple().isMusl() ? "ld.lld" : "hexagon-link";
+ }
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
+ void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+
StringRef GetGCCLibAndIncVersion() const { return GCCLibAndIncVersion.Text; }
bool IsIntegratedAssemblerDefault() const override {
return true;
diff --git a/clang/lib/Driver/ToolChains/Hurd.cpp b/clang/lib/Driver/ToolChains/Hurd.cpp
index 72166ca9f3594..a700d7b9064c3 100644
--- a/clang/lib/Driver/ToolChains/Hurd.cpp
+++ b/clang/lib/Driver/ToolChains/Hurd.cpp
@@ -61,21 +61,35 @@ static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
return Triple.isArch32Bit() ? "lib" : "lib64";
}
-Hurd::Hurd(const Driver &D, const llvm::Triple &Triple,
- const ArgList &Args)
+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();
std::string SysRoot = computeSysRoot();
+ ToolChain::path_list &PPaths = getProgramPaths();
+
+ Generic_GCC::PushPPaths(PPaths);
+
+ // 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
+ // possible permutations of these directories, and seeing which ones it added
+ // to the link paths.
path_list &Paths = getFilePaths();
- const std::string OSLibDir = getOSLibDir(Triple, Args);
+ const std::string OSLibDir = std::string(getOSLibDir(Triple, Args));
const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot);
#ifdef ENABLE_LINKER_BUILD_ID
ExtraOpts.push_back("--build-id");
#endif
- // If we are currently running Clang inside of the requested system root, add
- // its parent library paths to those searched.
+ Generic_GCC::AddMultilibPaths(D, SysRoot, OSLibDir, MultiarchTriple, Paths);
+
+ // Similar to the logic for GCC above, if we currently running Clang inside
+ // of the requested system root, add its parent library paths 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)) {
@@ -89,8 +103,11 @@ Hurd::Hurd(const Driver &D, const llvm::Triple &Triple,
addPathIfExists(D, SysRoot + "/usr/lib/" + MultiarchTriple, Paths);
addPathIfExists(D, SysRoot + "/usr/lib/../" + OSLibDir, Paths);
- // If we are currently running Clang inside of the requested system root, add
- // its parent library path to those searched.
+ 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))
@@ -108,13 +125,6 @@ Tool *Hurd::buildAssembler() const {
return new tools::gnutools::Assembler(*this);
}
-std::string Hurd::computeSysRoot() const {
- if (!getDriver().SysRoot.empty())
- return getDriver().SysRoot;
-
- return std::string();
-}
-
std::string Hurd::getDynamicLinker(const ArgList &Args) const {
if (getArch() == llvm::Triple::x86)
return "/lib/ld.so";
@@ -149,7 +159,7 @@ void Hurd::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
CIncludeDirs.split(Dirs, ":");
for (StringRef Dir : Dirs) {
StringRef Prefix =
- llvm::sys::path::is_absolute(Dir) ? StringRef(SysRoot) : "";
+ llvm::sys::path::is_absolute(Dir) ? "" : StringRef(SysRoot);
addExternCSystemInclude(DriverArgs, CC1Args, Prefix + Dir);
}
return;
@@ -157,6 +167,9 @@ void Hurd::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
// Lacking those, try to detect the correct set of system includes for the
// target triple.
+
+ AddMultilibIncludeArgs(DriverArgs, CC1Args);
+
if (getTriple().getArch() == llvm::Triple::x86) {
std::string Path = SysRoot + "/usr/include/i386-gnu";
if (D.getVFS().exists(Path))
@@ -170,3 +183,8 @@ void Hurd::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
}
+
+void Hurd::addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const {
+ for (const auto &Opt : ExtraOpts)
+ CmdArgs.push_back(Opt.c_str());
+}
diff --git a/clang/lib/Driver/ToolChains/Hurd.h b/clang/lib/Driver/ToolChains/Hurd.h
index 86c6c3f734dd9..0612a55280a87 100644
--- a/clang/lib/Driver/ToolChains/Hurd.h
+++ b/clang/lib/Driver/ToolChains/Hurd.h
@@ -27,9 +27,9 @@ public:
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- virtual std::string computeSysRoot() const;
+ std::string getDynamicLinker(const llvm::opt::ArgList &Args) const override;
- virtual std::string getDynamicLinker(const llvm::opt::ArgList &Args) const;
+ void addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const override;
std::vector<std::string> ExtraOpts;
diff --git a/clang/lib/Driver/ToolChains/InterfaceStubs.cpp b/clang/lib/Driver/ToolChains/InterfaceStubs.cpp
index 8f947e79bd1f1..f7c11421e8094 100644
--- a/clang/lib/Driver/ToolChains/InterfaceStubs.cpp
+++ b/clang/lib/Driver/ToolChains/InterfaceStubs.cpp
@@ -54,8 +54,9 @@ void Merger::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(InputFilename.c_str()));
}
- C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Merger),
- CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Args.MakeArgString(Merger), CmdArgs,
+ Inputs));
}
} // namespace ifstool
} // namespace tools
diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
index bff1ab1009be1..180350476c38b 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -208,15 +208,6 @@ static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
return Triple.isArch32Bit() ? "lib" : "lib64";
}
-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);
-}
-
Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
GCCInstallation.init(Triple, Args);
@@ -224,21 +215,9 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
SelectedMultilib = GCCInstallation.getMultilib();
llvm::Triple::ArchType Arch = Triple.getArch();
std::string SysRoot = computeSysRoot();
-
- // Cross-compiling binutils and GCC installations (vanilla and openSUSE at
- // least) put various tools in a triple-prefixed directory off of the parent
- // of the GCC installation. We use the GCC triple here to ensure that we end
- // up with tools that support the same amount of cross compiling as the
- // detected GCC installation. For example, if we find a GCC installation
- // targeting x86_64, but it is a bi-arch GCC installation, it can also be
- // used to target i386.
- // FIXME: This seems unlikely to be Linux-specific.
ToolChain::path_list &PPaths = getProgramPaths();
- if (GCCInstallation.isValid()) {
- PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +
- GCCInstallation.getTriple().str() + "/bin")
- .str());
- }
+
+ Generic_GCC::PushPPaths(PPaths);
Distro Distro(D.getVFS(), Triple);
@@ -253,10 +232,9 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
ExtraOpts.push_back("relro");
}
- // The lld default page size is too large for Aarch64, which produces much
- // larger .so files and images for arm64 device targets. Use 4KB page size
- // for Android arm64 targets instead.
- if (Triple.isAArch64() && Triple.isAndroid()) {
+ // Android ARM/AArch64 use max-page-size=4096 to reduce VMA usage. Note, lld
+ // from 11 onwards default max-page-size to 65536 for both ARM and AArch64.
+ if ((Triple.isARM() || Triple.isAArch64()) && Triple.isAndroid()) {
ExtraOpts.push_back("-z");
ExtraOpts.push_back("max-page-size=4096");
}
@@ -314,60 +292,10 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// to the link paths.
path_list &Paths = getFilePaths();
- const std::string OSLibDir = getOSLibDir(Triple, Args);
+ const std::string OSLibDir = std::string(getOSLibDir(Triple, Args));
const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot);
- // Add the multilib suffixed paths where they are available.
- if (GCCInstallation.isValid()) {
- const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
- const std::string &LibPath = GCCInstallation.getParentLibPath();
-
- // Add toolchain / multilib specific file paths.
- addMultilibsFilePaths(D, Multilibs, SelectedMultilib,
- GCCInstallation.getInstallPath(), Paths);
-
- // Sourcery CodeBench MIPS toolchain holds some libraries under
- // a biarch-like suffix of the GCC installation.
- addPathIfExists(
- D, GCCInstallation.getInstallPath() + SelectedMultilib.gccSuffix(),
- Paths);
-
- // GCC cross compiling toolchains will install target libraries which ship
- // as part of the toolchain under <prefix>/<triple>/<libdir> rather than as
- // any part of the GCC installation in
- // <prefix>/<libdir>/gcc/<triple>/<version>. This decision is somewhat
- // debatable, but is the reality today. We need to search this tree even
- // when we have a sysroot somewhere else. It is the responsibility of
- // whomever is doing the cross build targeting a sysroot using a GCC
- // installation that is *not* within the system root to ensure two things:
- //
- // 1) Any DSOs that are linked in from this tree or from the install path
- // above must be present on the system root and found via an
- // appropriate rpath.
- // 2) There must not be libraries installed into
- // <prefix>/<triple>/<libdir> unless they should be preferred over
- // those within the system root.
- //
- // Note that this matches the GCC behavior. See the below comment for where
- // Clang diverges from GCC's behavior.
- addPathIfExists(D, LibPath + "/../" + GCCTriple.str() + "/lib/../" +
- OSLibDir + SelectedMultilib.osSuffix(),
- Paths);
-
- // If the GCC installation we found is inside of the sysroot, we want to
- // prefer libraries installed in the parent prefix of the GCC installation.
- // It is important to *not* use these paths when the GCC installation is
- // outside of the system root as that can pick up unintended libraries.
- // This usually happens when there is an external cross compiler on the
- // host system, and a more minimal sysroot available that is the target of
- // 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)) {
- addPathIfExists(D, LibPath + "/" + MultiarchTriple, Paths);
- addPathIfExists(D, LibPath + "/../" + OSLibDir, Paths);
- }
- }
+ Generic_GCC::AddMultilibPaths(D, SysRoot, OSLibDir, MultiarchTriple, Paths);
// Similar to the logic for GCC above, if we currently running Clang inside
// of the requested system root, add its parent library paths to
@@ -411,36 +339,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
addPathIfExists(D, SysRoot + "/usr/" + OSLibDir + "/" + ABIName, Paths);
}
- // Try walking via the GCC triple path in case of biarch or multiarch GCC
- // installations with strange symlinks.
- if (GCCInstallation.isValid()) {
- addPathIfExists(D,
- SysRoot + "/usr/lib/" + GCCInstallation.getTriple().str() +
- "/../../" + OSLibDir,
- Paths);
-
- // Add the 'other' biarch variant path
- Multilib BiarchSibling;
- if (GCCInstallation.getBiarchSibling(BiarchSibling)) {
- addPathIfExists(D, GCCInstallation.getInstallPath() +
- BiarchSibling.gccSuffix(),
- Paths);
- }
-
- // See comments above on the multilib variant for details of why this is
- // included even from outside the sysroot.
- const std::string &LibPath = GCCInstallation.getParentLibPath();
- const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
- const Multilib &Multilib = GCCInstallation.getMultilib();
- addPathIfExists(D, LibPath + "/../" + GCCTriple.str() + "/lib" +
- Multilib.osSuffix(),
- Paths);
-
- // See comments above on the multilib variant for details of why this is
- // only included from within the sysroot.
- if (StringRef(LibPath).startswith(SysRoot))
- addPathIfExists(D, LibPath, 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
@@ -464,6 +363,10 @@ bool Linux::HasNativeLLVMSupport() const { return true; }
Tool *Linux::buildLinker() const { return new tools::gnutools::Linker(*this); }
+Tool *Linux::buildStaticLibTool() const {
+ return new tools::gnutools::StaticLibTool(*this);
+}
+
Tool *Linux::buildAssembler() const {
return new tools::gnutools::Assembler(*this);
}
@@ -638,6 +541,8 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
Loader = X32 ? "ld-linux-x32.so.2" : "ld-linux-x86-64.so.2";
break;
}
+ case llvm::Triple::ve:
+ return "/opt/nec/ve/lib/ld-linux-ve.so.1";
}
if (Distro == Distro::Exherbo &&
@@ -674,7 +579,7 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
CIncludeDirs.split(dirs, ":");
for (StringRef dir : dirs) {
StringRef Prefix =
- llvm::sys::path::is_absolute(dir) ? StringRef(SysRoot) : "";
+ llvm::sys::path::is_absolute(dir) ? "" : StringRef(SysRoot);
addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
}
return;
@@ -683,15 +588,7 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
// Lacking those, try to detect the correct set of system includes for the
// target triple.
- // Add include directories specific to the selected multilib set and multilib.
- if (GCCInstallation.isValid()) {
- const auto &Callback = Multilibs.includeDirsCallback();
- if (Callback) {
- for (const auto &Path : Callback(GCCInstallation.getMultilib()))
- addExternCSystemIncludeIfExists(
- DriverArgs, CC1Args, GCCInstallation.getInstallPath() + Path);
- }
- }
+ AddMultilibIncludeArgs(DriverArgs, CC1Args);
// Implement generic Debian multiarch support.
const StringRef X86_64MultiarchIncludeDirs[] = {
@@ -906,6 +803,11 @@ void Linux::AddCudaIncludeArgs(const ArgList &DriverArgs,
CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
}
+void Linux::AddHIPIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
+}
+
void Linux::AddIAMCUIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (GCCInstallation.isValid()) {
@@ -944,6 +846,7 @@ SanitizerMask Linux::getSupportedSanitizers() const {
getTriple().getArch() == llvm::Triple::thumb ||
getTriple().getArch() == llvm::Triple::armeb ||
getTriple().getArch() == llvm::Triple::thumbeb;
+ const bool IsSystemZ = getTriple().getArch() == llvm::Triple::systemz;
SanitizerMask Res = ToolChain::getSupportedSanitizers();
Res |= SanitizerKind::Address;
Res |= SanitizerKind::PointerCompare;
@@ -956,7 +859,8 @@ SanitizerMask Linux::getSupportedSanitizers() const {
Res |= SanitizerKind::SafeStack;
if (IsX86_64 || IsMIPS64 || IsAArch64)
Res |= SanitizerKind::DataFlow;
- if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsArmArch || IsPowerPC64)
+ if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsArmArch || IsPowerPC64 ||
+ IsSystemZ)
Res |= SanitizerKind::Leak;
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64)
Res |= SanitizerKind::Thread;
@@ -976,13 +880,34 @@ SanitizerMask Linux::getSupportedSanitizers() const {
void Linux::addProfileRTLibs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const {
- if (!needsProfileRT(Args)) return;
-
- // Add linker option -u__llvm_runtime_variable to cause runtime
+ // Add linker option -u__llvm_profile_runtime to cause runtime
// initialization module to be linked in.
- if ((!Args.hasArg(options::OPT_coverage)) &&
- (!Args.hasArg(options::OPT_ftest_coverage)))
+ if (needsProfileRT(Args))
CmdArgs.push_back(Args.MakeArgString(
Twine("-u", llvm::getInstrProfRuntimeHookVarName())));
ToolChain::addProfileRTLibs(Args, CmdArgs);
}
+
+llvm::DenormalMode
+Linux::getDefaultDenormalModeForType(const llvm::opt::ArgList &DriverArgs,
+ const JobAction &JA,
+ const llvm::fltSemantics *FPType) const {
+ switch (getTriple().getArch()) {
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64: {
+ std::string Unused;
+ // DAZ and FTZ are turned on in crtfastmath.o
+ if (!DriverArgs.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) &&
+ isFastMathRuntimeAvailable(DriverArgs, Unused))
+ return llvm::DenormalMode::getPreserveSign();
+ return llvm::DenormalMode::getIEEE();
+ }
+ default:
+ return llvm::DenormalMode::getIEEE();
+ }
+}
+
+void Linux::addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const {
+ for (const auto &Opt : ExtraOpts)
+ CmdArgs.push_back(Opt.c_str());
+}
diff --git a/clang/lib/Driver/ToolChains/Linux.h b/clang/lib/Driver/ToolChains/Linux.h
index f5518eac218a4..6b16b0e64990d 100644
--- a/clang/lib/Driver/ToolChains/Linux.h
+++ b/clang/lib/Driver/ToolChains/Linux.h
@@ -31,6 +31,8 @@ public:
llvm::opt::ArgStringList &CC1Args) const override;
void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+ void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
CXXStdlibType GetDefaultCXXStdlibType() const override;
@@ -40,15 +42,22 @@ public:
SanitizerMask getSupportedSanitizers() const override;
void addProfileRTLibs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
- virtual std::string computeSysRoot() const;
+ std::string computeSysRoot() const override;
- virtual std::string getDynamicLinker(const llvm::opt::ArgList &Args) const;
+ std::string getDynamicLinker(const llvm::opt::ArgList &Args) const override;
+
+ void addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const override;
std::vector<std::string> ExtraOpts;
+ llvm::DenormalMode getDefaultDenormalModeForType(
+ const llvm::opt::ArgList &DriverArgs, const JobAction &JA,
+ const llvm::fltSemantics *FPType = nullptr) const override;
+
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
+ Tool *buildStaticLibTool() const override;
std::string getMultiarchTriple(const Driver &D,
const llvm::Triple &TargetTriple,
diff --git a/clang/lib/Driver/ToolChains/MSP430.cpp b/clang/lib/Driver/ToolChains/MSP430.cpp
index bc77f015915dc..b0bc2e014b487 100644
--- a/clang/lib/Driver/ToolChains/MSP430.cpp
+++ b/clang/lib/Driver/ToolChains/MSP430.cpp
@@ -143,7 +143,7 @@ std::string MSP430ToolChain::computeSysRoot() const {
else
llvm::sys::path::append(Dir, getDriver().Dir, "..", getTriple().str());
- return Dir.str();
+ return std::string(Dir.str());
}
void MSP430ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
@@ -227,6 +227,7 @@ void msp430::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
- CmdArgs, Inputs));
+ C.addCommand(
+ std::make_unique<Command>(JA, *this, ResponseFileSupport::AtFileCurCP(),
+ Args.MakeArgString(Linker), CmdArgs, Inputs));
}
diff --git a/clang/lib/Driver/ToolChains/MSP430.h b/clang/lib/Driver/ToolChains/MSP430.h
index b5308a8dd6875..58fd158cd12f9 100644
--- a/clang/lib/Driver/ToolChains/MSP430.h
+++ b/clang/lib/Driver/ToolChains/MSP430.h
@@ -44,7 +44,7 @@ protected:
Tool *buildLinker() const override;
private:
- std::string computeSysRoot() const;
+ std::string computeSysRoot() const override;
};
} // end namespace toolchains
@@ -52,10 +52,9 @@ private:
namespace tools {
namespace msp430 {
-class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
- Linker(const ToolChain &TC)
- : GnuTool("MSP430::Linker", "msp430-elf-ld", TC) {}
+ Linker(const ToolChain &TC) : Tool("MSP430::Linker", "msp430-elf-ld", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
void ConstructJob(Compilation &C, const JobAction &JA,
diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp
index 4e143f6a5d3fa..6b3c00e2ab6d5 100644
--- a/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -128,13 +128,13 @@ static bool findVCToolChainViaEnvironment(std::string &Path,
llvm::StringRef ParentPath = llvm::sys::path::parent_path(TestPath);
llvm::StringRef ParentFilename = llvm::sys::path::filename(ParentPath);
if (ParentFilename == "VC") {
- Path = ParentPath;
+ Path = std::string(ParentPath);
VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
return true;
}
if (ParentFilename == "x86ret" || ParentFilename == "x86chk"
|| ParentFilename == "amd64ret" || ParentFilename == "amd64chk") {
- Path = ParentPath;
+ Path = std::string(ParentPath);
VSLayout = MSVCToolChain::ToolsetLayout::DevDivInternal;
return true;
}
@@ -163,7 +163,7 @@ static bool findVCToolChainViaEnvironment(std::string &Path,
for (int i = 0; i < 3; ++i)
ToolChainPath = llvm::sys::path::parent_path(ToolChainPath);
- Path = ToolChainPath;
+ Path = std::string(ToolChainPath);
VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
return true;
}
@@ -261,7 +261,7 @@ static bool findVCToolChainViaSetupConfig(std::string &Path,
if (!llvm::sys::fs::is_directory(ToolchainPath))
return false;
- Path = ToolchainPath.str();
+ Path = std::string(ToolchainPath.str());
VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
return true;
#endif
@@ -282,7 +282,7 @@ static bool findVCToolChainViaRegistry(std::string &Path,
VSInstallPath.c_str(), VSInstallPath.find(R"(\Common7\IDE)")));
llvm::sys::path::append(VCPath, "VC");
- Path = VCPath.str();
+ Path = std::string(VCPath.str());
VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
return true;
}
@@ -300,7 +300,8 @@ static std::string FindVisualStudioExecutable(const ToolChain &TC,
SmallString<128> FilePath(MSVC.getSubDirectoryPath(
toolchains::MSVCToolChain::SubDirectoryType::Bin));
llvm::sys::path::append(FilePath, Exe);
- return llvm::sys::fs::can_execute(FilePath) ? FilePath.str() : Exe;
+ return std::string(llvm::sys::fs::can_execute(FilePath) ? FilePath.str()
+ : Exe);
}
void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -349,6 +350,16 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath));
}
+ // 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()) {
+ if (TC.getVFS().exists(LibPath))
+ CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath));
+ }
+ auto CRTPath = TC.getCompilerRTPath();
+ if (TC.getVFS().exists(CRTPath))
+ CmdArgs.push_back(Args.MakeArgString("-libpath:" + CRTPath));
+
if (!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_L))
for (const auto &LibPath : Args.getAllArgValues(options::OPT_L))
CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath));
@@ -581,8 +592,9 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
linkPath = TC.GetProgramPath(Linker.str().c_str());
}
- auto LinkCmd = std::make_unique<Command>(
- JA, *this, Args.MakeArgString(linkPath), CmdArgs, Inputs);
+ auto LinkCmd =
+ std::make_unique<Command>(JA, *this, ResponseFileSupport::AtFileUTF16(),
+ Args.MakeArgString(linkPath), CmdArgs, Inputs);
if (!Environment.empty())
LinkCmd->setEnvironment(Environment);
C.addCommand(std::move(LinkCmd));
@@ -722,13 +734,15 @@ std::unique_ptr<Command> visualstudio::Compiler::GetCommand(
CmdArgs.push_back(Fo);
std::string Exec = FindVisualStudioExecutable(getToolChain(), "cl.exe");
- return std::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
- CmdArgs, Inputs);
+ return std::make_unique<Command>(JA, *this,
+ ResponseFileSupport::AtFileUTF16(),
+ Args.MakeArgString(Exec), CmdArgs, Inputs);
}
MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
- : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args) {
+ : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args),
+ RocmInstallation(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
@@ -786,8 +800,14 @@ void MSVCToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
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);
}
// Windows SDKs and VC Toolchains group their contents into subdirectories based
@@ -892,7 +912,7 @@ MSVCToolChain::getSubDirectoryPath(SubDirectoryType Type,
llvm::sys::path::append(Path, "lib", SubdirName);
break;
}
- return Path.str();
+ return std::string(Path.str());
}
#ifdef _WIN32
@@ -1046,7 +1066,7 @@ static bool getWindows10SDKVersionFromPath(const std::string &SDKPath,
if (!CandidateName.startswith("10."))
continue;
if (CandidateName > SDKVersion)
- SDKVersion = CandidateName;
+ SDKVersion = std::string(CandidateName);
}
return !SDKVersion.empty();
@@ -1129,7 +1149,7 @@ bool MSVCToolChain::getWindowsSDKLibraryPath(std::string &path) const {
}
}
- path = libPath.str();
+ path = std::string(libPath.str());
return true;
}
@@ -1168,7 +1188,7 @@ bool MSVCToolChain::getUniversalCRTLibraryPath(std::string &Path) const {
llvm::SmallString<128> LibPath(UniversalCRTSdkPath);
llvm::sys::path::append(LibPath, "Lib", UCRTVersion, "ucrt", ArchName);
- Path = LibPath.str();
+ Path = std::string(LibPath.str());
return true;
}
@@ -1475,14 +1495,15 @@ static void TranslateDArg(Arg *A, llvm::opt::DerivedArgList &DAL,
return;
}
- std::string NewVal = Val;
+ std::string NewVal = std::string(Val);
NewVal[Hash] = '=';
DAL.AddJoinedArg(A, Opts.getOption(options::OPT_D), NewVal);
}
llvm::opt::DerivedArgList *
MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
- StringRef BoundArch, Action::OffloadKind) const {
+ StringRef BoundArch,
+ Action::OffloadKind OFK) const {
DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
const OptTable &Opts = getDriver().getOpts();
@@ -1521,7 +1542,8 @@ MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
} else if (A->getOption().matches(options::OPT_D)) {
// Translate -Dfoo#bar into -Dfoo=bar.
TranslateDArg(A, *DAL, Opts);
- } else {
+ } else if (OFK != Action::OFK_HIP) {
+ // HIP Toolchain translates input args by itself.
DAL->append(A);
}
}
diff --git a/clang/lib/Driver/ToolChains/MSVC.h b/clang/lib/Driver/ToolChains/MSVC.h
index 41a69a82fecfe..dba99ed77246c 100644
--- a/clang/lib/Driver/ToolChains/MSVC.h
+++ b/clang/lib/Driver/ToolChains/MSVC.h
@@ -9,6 +9,7 @@
#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MSVC_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MSVC_H
+#include "AMDGPU.h"
#include "Cuda.h"
#include "clang/Basic/DebugInfoOptions.h"
#include "clang/Driver/Compilation.h"
@@ -23,9 +24,7 @@ namespace tools {
namespace visualstudio {
class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
- Linker(const ToolChain &TC)
- : Tool("visualstudio::Linker", "linker", TC, RF_Full,
- llvm::sys::WEM_UTF16) {}
+ Linker(const ToolChain &TC) : Tool("visualstudio::Linker", "linker", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
@@ -39,8 +38,7 @@ public:
class LLVM_LIBRARY_VISIBILITY Compiler : public Tool {
public:
Compiler(const ToolChain &TC)
- : Tool("visualstudio::Compiler", "compiler", TC, RF_Full,
- llvm::sys::WEM_UTF16) {}
+ : Tool("visualstudio::Compiler", "compiler", TC) {}
bool hasIntegratedAssembler() const override { return true; }
bool hasIntegratedCPP() const override { return true; }
@@ -125,6 +123,9 @@ public:
void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+ void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
bool getWindowsSDKLibraryPath(std::string &path) const;
/// Check if Universal CRT should be used if available
bool getUniversalCRTLibraryPath(std::string &path) const;
@@ -155,6 +156,7 @@ private:
std::string VCToolChainPath;
ToolsetLayout VSLayout = ToolsetLayout::OlderVS;
CudaInstallationDetector CudaInstallation;
+ RocmInstallationDetector RocmInstallation;
};
} // end namespace toolchains
diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp
index 8f24384e688b4..a1a1b413fb6c6 100644
--- a/clang/lib/Driver/ToolChains/MinGW.cpp
+++ b/clang/lib/Driver/ToolChains/MinGW.cpp
@@ -18,6 +18,7 @@
#include "llvm/Option/ArgList.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <system_error>
using namespace clang::diag;
@@ -49,7 +50,8 @@ void tools::MinGW::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(II.getFilename());
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Exec, CmdArgs, Inputs));
if (Args.hasArg(options::OPT_gsplit_dwarf))
SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
@@ -198,6 +200,17 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_L);
TC.AddFilePathLibArgs(Args, CmdArgs);
+
+ // Add the compiler-rt library directories if they exist to help
+ // the linker find the various sanitizer, builtin, and profiling runtimes.
+ for (const auto &LibPath : TC.getLibraryPaths()) {
+ if (TC.getVFS().exists(LibPath))
+ CmdArgs.push_back(Args.MakeArgString("-L" + LibPath));
+ }
+ auto CRTPath = TC.getCompilerRTPath();
+ if (TC.getVFS().exists(CRTPath))
+ CmdArgs.push_back(Args.MakeArgString("-L" + CRTPath));
+
AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
// TODO: Add profile stuff here
@@ -292,21 +305,25 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lkernel32");
}
- if (Args.hasArg(options::OPT_static))
+ if (Args.hasArg(options::OPT_static)) {
CmdArgs.push_back("--end-group");
- else
+ } else {
AddLibGCC(Args, CmdArgs);
+ if (!HasWindowsApp)
+ CmdArgs.push_back("-lkernel32");
+ }
}
if (!Args.hasArg(options::OPT_nostartfiles)) {
// Add crtfastmath.o if available and fast math is enabled.
- TC.AddFastMathRuntimeIfAvailable(Args, CmdArgs);
+ TC.addFastMathRuntimeIfAvailable(Args, CmdArgs);
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o")));
}
}
const char *Exec = Args.MakeArgString(TC.GetLinkerPath());
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs));
}
// Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple.
@@ -323,7 +340,7 @@ static bool findGccVersion(StringRef LibDir, std::string &GccLibDir,
continue;
if (CandidateVersion <= Version)
continue;
- Ver = VersionText;
+ Ver = std::string(VersionText);
GccLibDir = LI->path();
}
return Ver.size();
@@ -335,7 +352,7 @@ void toolchains::MinGW::findGccLibDir() {
Archs[0] += "-w64-mingw32";
Archs.emplace_back("mingw32");
if (Arch.empty())
- Arch = Archs[0].str();
+ Arch = std::string(Archs[0].str());
// lib: Arch Linux, Ubuntu, Windows
// lib64: openSUSE Linux
for (StringRef CandidateLib : {"lib", "lib64"}) {
@@ -343,7 +360,7 @@ void toolchains::MinGW::findGccLibDir() {
llvm::SmallString<1024> LibDir(Base);
llvm::sys::path::append(LibDir, CandidateLib, "gcc", CandidateArch);
if (findGccVersion(LibDir, GccLibDir, Ver)) {
- Arch = CandidateArch;
+ Arch = std::string(CandidateArch);
return;
}
}
@@ -372,7 +389,7 @@ llvm::ErrorOr<std::string> toolchains::MinGW::findClangRelativeSysroot() {
StringRef Sep = llvm::sys::path::get_separator();
for (StringRef CandidateSubdir : Subdirs) {
if (llvm::sys::fs::is_directory(ClangRoot + Sep + CandidateSubdir)) {
- Arch = CandidateSubdir;
+ Arch = std::string(CandidateSubdir);
return (ClangRoot + Sep + CandidateSubdir).str();
}
}
@@ -381,7 +398,8 @@ llvm::ErrorOr<std::string> toolchains::MinGW::findClangRelativeSysroot() {
toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
- : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args) {
+ : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args),
+ RocmInstallation(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().SysRoot.size())
@@ -389,12 +407,13 @@ toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple,
// 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())
- Base = llvm::sys::path::parent_path(TargetSubdir.get());
+ Base = std::string(llvm::sys::path::parent_path(TargetSubdir.get()));
else if (llvm::ErrorOr<std::string> GPPName = findGcc())
- Base = llvm::sys::path::parent_path(
- llvm::sys::path::parent_path(GPPName.get()));
+ Base = std::string(llvm::sys::path::parent_path(
+ llvm::sys::path::parent_path(GPPName.get())));
else
- Base = llvm::sys::path::parent_path(getDriver().getInstalledDir());
+ Base = std::string(
+ llvm::sys::path::parent_path(getDriver().getInstalledDir()));
Base += llvm::sys::path::get_separator();
findGccLibDir();
@@ -482,8 +501,14 @@ void toolchains::MinGW::AddCudaIncludeArgs(const ArgList &DriverArgs,
CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
}
+void toolchains::MinGW::AddHIPIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
+}
+
void toolchains::MinGW::printVerboseInfo(raw_ostream &OS) const {
CudaInstallation.print(OS);
+ RocmInstallation.print(OS);
}
// Include directories for various hosts:
diff --git a/clang/lib/Driver/ToolChains/MinGW.h b/clang/lib/Driver/ToolChains/MinGW.h
index 6752a405be879..2f1559fcf34cd 100644
--- a/clang/lib/Driver/ToolChains/MinGW.h
+++ b/clang/lib/Driver/ToolChains/MinGW.h
@@ -11,8 +11,10 @@
#include "Cuda.h"
#include "Gnu.h"
+#include "ROCm.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
+#include "llvm/Support/ErrorOr.h"
namespace clang {
namespace driver {
@@ -34,8 +36,7 @@ public:
class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
- Linker(const ToolChain &TC)
- : Tool("MinGW::Linker", "linker", TC, Tool::RF_Full) {}
+ Linker(const ToolChain &TC) : Tool("MinGW::Linker", "linker", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
@@ -81,6 +82,8 @@ public:
void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+ void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
void printVerboseInfo(raw_ostream &OS) const override;
@@ -91,6 +94,7 @@ protected:
private:
CudaInstallationDetector CudaInstallation;
+ RocmInstallationDetector RocmInstallation;
std::string Base;
std::string GccLibDir;
diff --git a/clang/lib/Driver/ToolChains/Minix.cpp b/clang/lib/Driver/ToolChains/Minix.cpp
index 6947049ea52ee..d0314795620ce 100644
--- a/clang/lib/Driver/ToolChains/Minix.cpp
+++ b/clang/lib/Driver/ToolChains/Minix.cpp
@@ -36,7 +36,8 @@ void tools::minix::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(II.getFilename());
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
}
void tools::minix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -88,7 +89,8 @@ void tools::minix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
}
/// Minix - Minix tool chain which can call as(1) and ld(1) directly.
diff --git a/clang/lib/Driver/ToolChains/Minix.h b/clang/lib/Driver/ToolChains/Minix.h
index 1ed6acebab9c0..af8d59c5085a9 100644
--- a/clang/lib/Driver/ToolChains/Minix.h
+++ b/clang/lib/Driver/ToolChains/Minix.h
@@ -18,10 +18,9 @@ namespace driver {
namespace tools {
/// minix -- Directly call GNU Binutils assembler and linker
namespace minix {
-class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
public:
- Assembler(const ToolChain &TC)
- : GnuTool("minix::Assembler", "assembler", TC) {}
+ Assembler(const ToolChain &TC) : Tool("minix::Assembler", "assembler", TC) {}
bool hasIntegratedCPP() const override { return false; }
@@ -31,9 +30,9 @@ public:
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
- Linker(const ToolChain &TC) : GnuTool("minix::Linker", "linker", TC) {}
+ Linker(const ToolChain &TC) : Tool("minix::Linker", "linker", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
diff --git a/clang/lib/Driver/ToolChains/MipsLinux.cpp b/clang/lib/Driver/ToolChains/MipsLinux.cpp
index cfda7f4bb4dfd..41b7b839f3b32 100644
--- a/clang/lib/Driver/ToolChains/MipsLinux.cpp
+++ b/clang/lib/Driver/ToolChains/MipsLinux.cpp
@@ -136,5 +136,5 @@ std::string MipsLLVMToolChain::getCompilerRT(const ArgList &Args,
}
llvm::sys::path::append(
Path, Twine("libclang_rt." + Component + "-" + "mips" + Suffix));
- return Path.str();
+ return std::string(Path.str());
}
diff --git a/clang/lib/Driver/ToolChains/Myriad.cpp b/clang/lib/Driver/ToolChains/Myriad.cpp
index 2ce0f13ce3d1a..84fe4748b6faf 100644
--- a/clang/lib/Driver/ToolChains/Myriad.cpp
+++ b/clang/lib/Driver/ToolChains/Myriad.cpp
@@ -77,8 +77,9 @@ void tools::SHAVE::Compiler::ConstructJob(Compilation &C, const JobAction &JA,
std::string Exec =
Args.MakeArgString(getToolChain().GetProgramPath("moviCompile"));
- C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
- CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Args.MakeArgString(Exec), CmdArgs,
+ Inputs));
}
void tools::SHAVE::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
@@ -112,8 +113,9 @@ void tools::SHAVE::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
std::string Exec =
Args.MakeArgString(getToolChain().GetProgramPath("moviAsm"));
- C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
- CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Args.MakeArgString(Exec), CmdArgs,
+ Inputs));
}
void tools::Myriad::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -198,8 +200,9 @@ void tools::Myriad::Linker::ConstructJob(Compilation &C, const JobAction &JA,
std::string Exec =
Args.MakeArgString(TC.GetProgramPath("sparc-myriad-rtems-ld"));
- C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
- CmdArgs, Inputs));
+ C.addCommand(
+ std::make_unique<Command>(JA, *this, ResponseFileSupport::AtFileCurCP(),
+ Args.MakeArgString(Exec), CmdArgs, Inputs));
}
MyriadToolChain::MyriadToolChain(const Driver &D, const llvm::Triple &Triple,
diff --git a/clang/lib/Driver/ToolChains/Myriad.h b/clang/lib/Driver/ToolChains/Myriad.h
index 9f5225fbc62c9..cae574bdcfea3 100644
--- a/clang/lib/Driver/ToolChains/Myriad.h
+++ b/clang/lib/Driver/ToolChains/Myriad.h
@@ -49,9 +49,9 @@ public:
/// 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 GnuTool {
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
- Linker(const ToolChain &TC) : GnuTool("shave::Linker", "ld", TC) {}
+ 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,
diff --git a/clang/lib/Driver/ToolChains/NaCl.cpp b/clang/lib/Driver/ToolChains/NaCl.cpp
index 97241c8840273..15a773675299a 100644
--- a/clang/lib/Driver/ToolChains/NaCl.cpp
+++ b/clang/lib/Driver/ToolChains/NaCl.cpp
@@ -193,7 +193,8 @@ void nacltools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
}
/// NaCl Toolchain
diff --git a/clang/lib/Driver/ToolChains/NaCl.h b/clang/lib/Driver/ToolChains/NaCl.h
index ab243f8087bb1..5e5fdb583bb60 100644
--- a/clang/lib/Driver/ToolChains/NaCl.h
+++ b/clang/lib/Driver/ToolChains/NaCl.h
@@ -27,9 +27,9 @@ public:
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
- Linker(const ToolChain &TC) : GnuTool("NaCl::Linker", "linker", TC) {}
+ Linker(const ToolChain &TC) : Tool("NaCl::Linker", "linker", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
diff --git a/clang/lib/Driver/ToolChains/NetBSD.cpp b/clang/lib/Driver/ToolChains/NetBSD.cpp
index 0100a387d6c35..253ee6ce0f721 100644
--- a/clang/lib/Driver/ToolChains/NetBSD.cpp
+++ b/clang/lib/Driver/ToolChains/NetBSD.cpp
@@ -103,7 +103,8 @@ void netbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(II.getFilename());
const char *Exec = Args.MakeArgString((getToolChain().GetProgramPath("as")));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
}
void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -337,7 +338,8 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
ToolChain.addProfileRTLibs(Args, CmdArgs);
const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
}
/// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly.
diff --git a/clang/lib/Driver/ToolChains/NetBSD.h b/clang/lib/Driver/ToolChains/NetBSD.h
index 6d404263f625c..8348554fd1492 100644
--- a/clang/lib/Driver/ToolChains/NetBSD.h
+++ b/clang/lib/Driver/ToolChains/NetBSD.h
@@ -19,10 +19,9 @@ namespace tools {
/// netbsd -- Directly call GNU Binutils assembler and linker
namespace netbsd {
-class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
public:
- Assembler(const ToolChain &TC)
- : GnuTool("netbsd::Assembler", "assembler", TC) {}
+ Assembler(const ToolChain &TC) : Tool("netbsd::Assembler", "assembler", TC) {}
bool hasIntegratedCPP() const override { return false; }
@@ -32,9 +31,9 @@ public:
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
- Linker(const ToolChain &TC) : GnuTool("netbsd::Linker", "linker", TC) {}
+ Linker(const ToolChain &TC) : Tool("netbsd::Linker", "linker", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
diff --git a/clang/lib/Driver/ToolChains/OpenBSD.cpp b/clang/lib/Driver/ToolChains/OpenBSD.cpp
index 80343c0394cb5..9c1a9c5f82280 100644
--- a/clang/lib/Driver/ToolChains/OpenBSD.cpp
+++ b/clang/lib/Driver/ToolChains/OpenBSD.cpp
@@ -89,7 +89,8 @@ void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(II.getFilename());
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
}
void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -227,7 +228,8 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
}
SanitizerMask OpenBSD::getSupportedSanitizers() const {
diff --git a/clang/lib/Driver/ToolChains/OpenBSD.h b/clang/lib/Driver/ToolChains/OpenBSD.h
index 9f1ee0f66402b..897eee57ab684 100644
--- a/clang/lib/Driver/ToolChains/OpenBSD.h
+++ b/clang/lib/Driver/ToolChains/OpenBSD.h
@@ -19,10 +19,10 @@ namespace tools {
/// openbsd -- Directly call GNU Binutils assembler and linker
namespace openbsd {
-class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
public:
Assembler(const ToolChain &TC)
- : GnuTool("openbsd::Assembler", "assembler", TC) {}
+ : Tool("openbsd::Assembler", "assembler", TC) {}
bool hasIntegratedCPP() const override { return false; }
@@ -32,9 +32,9 @@ public:
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
- Linker(const ToolChain &TC) : GnuTool("openbsd::Linker", "linker", TC) {}
+ Linker(const ToolChain &TC) : Tool("openbsd::Linker", "linker", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
diff --git a/clang/lib/Driver/ToolChains/PS4CPU.cpp b/clang/lib/Driver/ToolChains/PS4CPU.cpp
index 4e8840296205d..6dc81899cbaac 100644
--- a/clang/lib/Driver/ToolChains/PS4CPU.cpp
+++ b/clang/lib/Driver/ToolChains/PS4CPU.cpp
@@ -30,13 +30,17 @@ void tools::PS4cpu::addProfileRTArgs(const ToolChain &TC, const ArgList &Args,
if ((Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
false) ||
Args.hasFlag(options::OPT_fprofile_generate,
- options::OPT_fno_profile_instr_generate, false) ||
+ options::OPT_fno_profile_generate, false) ||
Args.hasFlag(options::OPT_fprofile_generate_EQ,
- options::OPT_fno_profile_instr_generate, false) ||
+ 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("--dependent-lib=libclang_rt.profile-x86_64.a");
@@ -62,7 +66,8 @@ void tools::PS4cpu::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("orbis-as"));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs));
}
static void AddPS4SanitizerArgs(const ToolChain &TC, ArgStringList &CmdArgs) {
@@ -84,13 +89,13 @@ void tools::PS4cpu::addSanitizerArgs(const ToolChain &TC,
CmdArgs.push_back("--dependent-lib=libSceDbgAddressSanitizer_stub_weak.a");
}
-static void ConstructPS4LinkJob(const Tool &T, Compilation &C,
- const JobAction &JA, const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) {
+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 &>(T.getToolChain());
+ static_cast<const toolchains::FreeBSD &>(getToolChain());
const Driver &D = ToolChain.getDriver();
ArgStringList CmdArgs;
@@ -139,216 +144,16 @@ static void ConstructPS4LinkJob(const Tool &T, Compilation &C,
CmdArgs.push_back("-lpthread");
}
- const char *Exec = Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld"));
-
- C.addCommand(std::make_unique<Command>(JA, T, Exec, CmdArgs, Inputs));
-}
-
-static void ConstructGoldLinkJob(const Tool &T, Compilation &C,
- const JobAction &JA, const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) {
- const toolchains::FreeBSD &ToolChain =
- static_cast<const toolchains::FreeBSD &>(T.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_pie))
- CmdArgs.push_back("-pie");
-
- if (Args.hasArg(options::OPT_static)) {
- CmdArgs.push_back("-Bstatic");
- } else {
- if (Args.hasArg(options::OPT_rdynamic))
- CmdArgs.push_back("-export-dynamic");
- CmdArgs.push_back("--eh-frame-hdr");
- if (Args.hasArg(options::OPT_shared)) {
- CmdArgs.push_back("-Bshareable");
- } else {
- CmdArgs.push_back("-dynamic-linker");
- CmdArgs.push_back("/libexec/ld-elf.so.1");
- }
- CmdArgs.push_back("--enable-new-dtags");
- }
-
- 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);
-
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
- const char *crt1 = nullptr;
- if (!Args.hasArg(options::OPT_shared)) {
- if (Args.hasArg(options::OPT_pg))
- crt1 = "gcrt1.o";
- else if (Args.hasArg(options::OPT_pie))
- crt1 = "Scrt1.o";
- else
- crt1 = "crt1.o";
- }
- if (crt1)
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));
-
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
-
- const char *crtbegin = nullptr;
- if (Args.hasArg(options::OPT_static))
- crtbegin = "crtbeginT.o";
- else if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
- crtbegin = "crtbeginS.o";
- else
- crtbegin = "crtbegin.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);
- Args.AddAllArgs(CmdArgs, options::OPT_e);
- Args.AddAllArgs(CmdArgs, options::OPT_s);
- Args.AddAllArgs(CmdArgs, options::OPT_t);
- Args.AddAllArgs(CmdArgs, options::OPT_r);
-
- if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
- CmdArgs.push_back("--no-demangle");
-
- AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
-
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
- // For PS4, we always want to pass libm, libstdc++ and libkernel
- // libraries for both C and C++ compilations.
- CmdArgs.push_back("-lkernel");
- if (D.CCCIsCXX()) {
- if (ToolChain.ShouldLinkCXXStdlib(Args))
- ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
- if (Args.hasArg(options::OPT_pg))
- CmdArgs.push_back("-lm_p");
- else
- CmdArgs.push_back("-lm");
- }
- // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
- // the default system libraries. Just mimic this for now.
- if (Args.hasArg(options::OPT_pg))
- CmdArgs.push_back("-lgcc_p");
- else
- CmdArgs.push_back("-lcompiler_rt");
- if (Args.hasArg(options::OPT_static)) {
- CmdArgs.push_back("-lstdc++");
- } else if (Args.hasArg(options::OPT_pg)) {
- CmdArgs.push_back("-lgcc_eh_p");
- } else {
- CmdArgs.push_back("--as-needed");
- CmdArgs.push_back("-lstdc++");
- CmdArgs.push_back("--no-as-needed");
- }
-
- if (Args.hasArg(options::OPT_pthread)) {
- if (Args.hasArg(options::OPT_pg))
- CmdArgs.push_back("-lpthread_p");
- else
- CmdArgs.push_back("-lpthread");
- }
-
- if (Args.hasArg(options::OPT_pg)) {
- if (Args.hasArg(options::OPT_shared))
- CmdArgs.push_back("-lc");
- else {
- if (Args.hasArg(options::OPT_static)) {
- CmdArgs.push_back("--start-group");
- CmdArgs.push_back("-lc_p");
- CmdArgs.push_back("-lpthread_p");
- CmdArgs.push_back("--end-group");
- } else {
- CmdArgs.push_back("-lc_p");
- }
- }
- CmdArgs.push_back("-lgcc_p");
- } else {
- if (Args.hasArg(options::OPT_static)) {
- CmdArgs.push_back("--start-group");
- CmdArgs.push_back("-lc");
- CmdArgs.push_back("-lpthread");
- CmdArgs.push_back("--end-group");
- } else {
- CmdArgs.push_back("-lc");
- }
- CmdArgs.push_back("-lcompiler_rt");
- }
-
- if (Args.hasArg(options::OPT_static)) {
- CmdArgs.push_back("-lstdc++");
- } else if (Args.hasArg(options::OPT_pg)) {
- CmdArgs.push_back("-lgcc_eh_p");
- } else {
- CmdArgs.push_back("--as-needed");
- CmdArgs.push_back("-lstdc++");
- CmdArgs.push_back("--no-as-needed");
- }
- }
-
- 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")));
+ if (Args.hasArg(options::OPT_fuse_ld_EQ)) {
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << "-fuse-ld" << getToolChain().getTriple().str();
}
const char *Exec =
-#ifdef _WIN32
- Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld.gold"));
-#else
Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld"));
-#endif
-
- C.addCommand(std::make_unique<Command>(JA, T, Exec, CmdArgs, Inputs));
-}
-
-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();
- bool PS4Linker;
- StringRef LinkerOptName;
- if (const Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
- LinkerOptName = A->getValue();
- if (LinkerOptName != "ps4" && LinkerOptName != "gold")
- D.Diag(diag::err_drv_unsupported_linker) << LinkerOptName;
- }
- if (LinkerOptName == "gold")
- PS4Linker = false;
- else if (LinkerOptName == "ps4")
- PS4Linker = true;
- else
- PS4Linker = !Args.hasArg(options::OPT_shared);
-
- if (PS4Linker)
- ConstructPS4LinkJob(*this, C, JA, Output, Inputs, Args, LinkingOutput);
- else
- ConstructGoldLinkJob(*this, C, JA, Output, Inputs, Args, LinkingOutput);
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs));
}
toolchains::PS4CPU::PS4CPU(const Driver &D, const llvm::Triple &Triple,
@@ -382,7 +187,7 @@ toolchains::PS4CPU::PS4CPU(const Driver &D, const llvm::Triple &Triple,
if (!llvm::sys::fs::exists(PrefixDir))
getDriver().Diag(clang::diag::warn_missing_sysroot) << PrefixDir;
} else
- PrefixDir = PS4SDKDir.str();
+ PrefixDir = std::string(PS4SDKDir.str());
SmallString<512> PS4SDKIncludeDir(PrefixDir);
llvm::sys::path::append(PS4SDKIncludeDir, "target/include");
@@ -407,7 +212,7 @@ toolchains::PS4CPU::PS4CPU(const Driver &D, const llvm::Triple &Triple,
<< "PS4 system libraries" << PS4SDKLibDir;
return;
}
- getFilePaths().push_back(PS4SDKLibDir.str());
+ getFilePaths().push_back(std::string(PS4SDKLibDir.str()));
}
Tool *toolchains::PS4CPU::buildAssembler() const {
@@ -430,3 +235,17 @@ SanitizerMask toolchains::PS4CPU::getSupportedSanitizers() const {
Res |= SanitizerKind::Vptr;
return Res;
}
+
+void toolchains::PS4CPU::addClangTargetOptions(
+ const ArgList &DriverArgs,
+ ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadingKind) const {
+ // PS4 does 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)
+ << A->getAsString(DriverArgs) << getTriple().str();
+ }
+
+ CC1Args.push_back("-fno-use-init-array");
+}
diff --git a/clang/lib/Driver/ToolChains/PS4CPU.h b/clang/lib/Driver/ToolChains/PS4CPU.h
index 18852b2808cbd..968be015d4113 100644
--- a/clang/lib/Driver/ToolChains/PS4CPU.h
+++ b/clang/lib/Driver/ToolChains/PS4CPU.h
@@ -26,8 +26,7 @@ void addSanitizerArgs(const ToolChain &TC, llvm::opt::ArgStringList &CmdArgs);
class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
public:
- Assemble(const ToolChain &TC)
- : Tool("PS4cpu::Assemble", "assembler", TC, RF_Full) {}
+ Assemble(const ToolChain &TC) : Tool("PS4cpu::Assemble", "assembler", TC) {}
bool hasIntegratedCPP() const override { return false; }
@@ -40,7 +39,7 @@ public:
class LLVM_LIBRARY_VISIBILITY Link : public Tool {
public:
- Link(const ToolChain &TC) : Tool("PS4cpu::Link", "linker", TC, RF_Full) {}
+ Link(const ToolChain &TC) : Tool("PS4cpu::Link", "linker", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
@@ -88,6 +87,20 @@ public:
// 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;
+
+ llvm::DenormalMode getDefaultDenormalModeForType(
+ const llvm::opt::ArgList &DriverArgs, const JobAction &JA,
+ const llvm::fltSemantics *FPType) const override {
+ // DAZ and FTZ are on by default.
+ return llvm::DenormalMode::getPreserveSign();
+ }
+
+ bool useRelaxRelocations() const override { return true; }
+
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
diff --git a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
index ddc329e3c722b..cc912d94cb92f 100644
--- a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
+++ b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
@@ -119,7 +119,7 @@ std::string RISCVToolChain::computeSysRoot() const {
if (!llvm::sys::fs::exists(SysRootDir))
return std::string();
- return SysRootDir.str();
+ return std::string(SysRootDir.str());
}
void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -142,7 +142,7 @@ void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("elf32lriscv");
}
- std::string Linker = getToolChain().GetProgramPath(getShortName());
+ std::string Linker = getToolChain().GetLinkerPath();
bool WantCRTs =
!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles);
@@ -191,7 +191,8 @@ void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
- CmdArgs, Inputs));
+ C.addCommand(
+ std::make_unique<Command>(JA, *this, ResponseFileSupport::AtFileCurCP(),
+ Args.MakeArgString(Linker), CmdArgs, Inputs));
}
// RISCV tools end.
diff --git a/clang/lib/Driver/ToolChains/RISCVToolchain.h b/clang/lib/Driver/ToolChains/RISCVToolchain.h
index bb7f64849bcb6..4734aee5f1ab7 100644
--- a/clang/lib/Driver/ToolChains/RISCVToolchain.h
+++ b/clang/lib/Driver/ToolChains/RISCVToolchain.h
@@ -39,16 +39,16 @@ protected:
Tool *buildLinker() const override;
private:
- std::string computeSysRoot() const;
+ std::string computeSysRoot() const override;
};
} // end namespace toolchains
namespace tools {
namespace RISCV {
-class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
- Linker(const ToolChain &TC) : GnuTool("RISCV::Linker", "ld", TC) {}
+ Linker(const ToolChain &TC) : Tool("RISCV::Linker", "ld", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
void ConstructJob(Compilation &C, const JobAction &JA,
diff --git a/clang/lib/Driver/ToolChains/ROCm.h b/clang/lib/Driver/ToolChains/ROCm.h
new file mode 100644
index 0000000000000..962c72fedfe07
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/ROCm.h
@@ -0,0 +1,228 @@
+//===--- ROCm.h - ROCm installation detector --------------------*- 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_ROCM_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ROCM_H
+
+#include "clang/Basic/Cuda.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/Options.h"
+#include "llvm/ADT/SmallSet.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"
+
+namespace clang {
+namespace driver {
+
+/// A class to find a viable ROCM installation
+/// TODO: Generalize to handle libclc.
+class RocmInstallationDetector {
+private:
+ struct ConditionalLibrary {
+ SmallString<0> On;
+ SmallString<0> Off;
+
+ bool isValid() const { return !On.empty() && !Off.empty(); }
+
+ StringRef get(bool Enabled) const {
+ assert(isValid());
+ return Enabled ? On : Off;
+ }
+ };
+
+ // Installation path candidate.
+ struct Candidate {
+ llvm::SmallString<0> Path;
+ bool StrictChecking;
+
+ Candidate(std::string Path, bool StrictChecking = false)
+ : Path(Path), StrictChecking(StrictChecking) {}
+ };
+
+ const Driver &D;
+ bool HasHIPRuntime = false;
+ bool HasDeviceLibrary = false;
+
+ // Default version if not detected or specified.
+ const unsigned DefaultVersionMajor = 3;
+ const unsigned DefaultVersionMinor = 5;
+ const char *DefaultVersionPatch = "0";
+
+ // The version string in Major.Minor.Patch format.
+ std::string DetectedVersion;
+ // Version containing major and minor.
+ llvm::VersionTuple VersionMajorMinor;
+ // Version containing patch.
+ std::string VersionPatch;
+
+ // ROCm path specified by --rocm-path.
+ StringRef RocmPathArg;
+ // ROCm device library paths specified by --rocm-device-lib-path.
+ std::vector<std::string> RocmDeviceLibPathArg;
+ // HIP version specified by --hip-version.
+ StringRef HIPVersionArg;
+ // Wheter -nogpulib is specified.
+ bool NoBuiltinLibs = false;
+
+ // Paths
+ SmallString<0> InstallPath;
+ SmallString<0> BinPath;
+ SmallString<0> LibPath;
+ SmallString<0> LibDevicePath;
+ SmallString<0> IncludePath;
+ llvm::StringMap<std::string> LibDeviceMap;
+
+ // Libraries that are always linked.
+ SmallString<0> OCML;
+ SmallString<0> OCKL;
+
+ // Libraries that are always linked depending on the language
+ SmallString<0> OpenCL;
+ SmallString<0> HIP;
+
+ // Libraries swapped based on compile flags.
+ ConditionalLibrary WavefrontSize64;
+ ConditionalLibrary FiniteOnly;
+ ConditionalLibrary UnsafeMath;
+ ConditionalLibrary DenormalsAreZero;
+ ConditionalLibrary CorrectlyRoundedSqrt;
+
+ bool allGenericLibsValid() const {
+ return !OCML.empty() && !OCKL.empty() && !OpenCL.empty() && !HIP.empty() &&
+ WavefrontSize64.isValid() && FiniteOnly.isValid() &&
+ UnsafeMath.isValid() && DenormalsAreZero.isValid() &&
+ CorrectlyRoundedSqrt.isValid();
+ }
+
+ // GPU architectures for which we have raised an error in
+ // CheckRocmVersionSupportsArch.
+ mutable llvm::SmallSet<CudaArch, 4> ArchsWithBadVersion;
+
+ void scanLibDevicePath(llvm::StringRef Path);
+ void ParseHIPVersionFile(llvm::StringRef V);
+ SmallVector<Candidate, 4> getInstallationPathCandidates();
+
+public:
+ RocmInstallationDetector(const Driver &D, const llvm::Triple &HostTriple,
+ const llvm::opt::ArgList &Args,
+ bool DetectHIPRuntime = true,
+ bool DetectDeviceLib = false);
+
+ /// Add arguments needed to link default bitcode libraries.
+ void addCommonBitcodeLibCC1Args(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ StringRef LibDeviceFile, bool Wave64,
+ bool DAZ, bool FiniteOnly, bool UnsafeMathOpt,
+ bool FastRelaxedMath, bool CorrectSqrt) const;
+
+ /// Emit an error if Version does not support the given Arch.
+ ///
+ /// If either Version or Arch is unknown, does not emit an error. Emits at
+ /// most one error per Arch.
+ void CheckRocmVersionSupportsArch(CudaArch Arch) const;
+
+ /// Check whether we detected a valid HIP runtime.
+ bool hasHIPRuntime() const { return HasHIPRuntime; }
+
+ /// Check whether we detected a valid ROCm device library.
+ bool hasDeviceLibrary() const { return HasDeviceLibrary; }
+
+ /// Print information about the detected ROCm installation.
+ void print(raw_ostream &OS) const;
+
+ /// Get the detected Rocm install's version.
+ // RocmVersion version() const { return Version; }
+
+ /// Get the detected Rocm installation path.
+ StringRef getInstallPath() const { return InstallPath; }
+
+ /// Get the detected path to Rocm's bin directory.
+ // StringRef getBinPath() const { return BinPath; }
+
+ /// Get the detected Rocm Include path.
+ StringRef getIncludePath() const { return IncludePath; }
+
+ /// Get the detected Rocm library path.
+ StringRef getLibPath() const { return LibPath; }
+
+ /// Get the detected Rocm device library path.
+ StringRef getLibDevicePath() const { return LibDevicePath; }
+
+ StringRef getOCMLPath() const {
+ assert(!OCML.empty());
+ return OCML;
+ }
+
+ StringRef getOCKLPath() const {
+ assert(!OCKL.empty());
+ return OCKL;
+ }
+
+ StringRef getOpenCLPath() const {
+ assert(!OpenCL.empty());
+ return OpenCL;
+ }
+
+ StringRef getHIPPath() const {
+ assert(!HIP.empty());
+ return HIP;
+ }
+
+ StringRef getWavefrontSize64Path(bool Enabled) const {
+ return WavefrontSize64.get(Enabled);
+ }
+
+ StringRef getFiniteOnlyPath(bool Enabled) const {
+ return FiniteOnly.get(Enabled);
+ }
+
+ StringRef getUnsafeMathPath(bool Enabled) const {
+ return UnsafeMath.get(Enabled);
+ }
+
+ StringRef getDenormalsAreZeroPath(bool Enabled) const {
+ return DenormalsAreZero.get(Enabled);
+ }
+
+ StringRef getCorrectlyRoundedSqrtPath(bool Enabled) const {
+ return CorrectlyRoundedSqrt.get(Enabled);
+ }
+
+ /// Get libdevice file for given architecture
+ std::string getLibDeviceFile(StringRef Gpu) const {
+ return LibDeviceMap.lookup(Gpu);
+ }
+
+ void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+
+ void detectDeviceLibrary();
+ void detectHIPRuntime();
+
+ /// Get the values for --rocm-device-lib-path arguments
+ std::vector<std::string> getRocmDeviceLibPathArg() const {
+ return RocmDeviceLibPathArg;
+ }
+
+ /// Get the value for --rocm-path argument
+ StringRef getRocmPathArg() const { return RocmPathArg; }
+
+ /// Get the value for --hip-version argument
+ StringRef getHIPVersionArg() const { return HIPVersionArg; }
+
+ std::string getHIPVersion() const { return DetectedVersion; }
+};
+
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ROCM_H
diff --git a/clang/lib/Driver/ToolChains/Solaris.cpp b/clang/lib/Driver/ToolChains/Solaris.cpp
index fc4e2cf151ef1..b8fdc87478bc6 100644
--- a/clang/lib/Driver/ToolChains/Solaris.cpp
+++ b/clang/lib/Driver/ToolChains/Solaris.cpp
@@ -41,7 +41,8 @@ void solaris::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(II.getFilename());
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Exec, CmdArgs, Inputs));
}
void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -150,7 +151,8 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
getToolChain().addProfileRTLibs(Args, CmdArgs);
const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Exec, CmdArgs, Inputs));
}
static StringRef getSolarisLibSuffix(const llvm::Triple &Triple) {
@@ -244,7 +246,7 @@ void Solaris::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
CIncludeDirs.split(dirs, ":");
for (StringRef dir : dirs) {
StringRef Prefix =
- llvm::sys::path::is_absolute(dir) ? StringRef(D.SysRoot) : "";
+ llvm::sys::path::is_absolute(dir) ? "" : StringRef(D.SysRoot);
addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
}
return;
diff --git a/clang/lib/Driver/ToolChains/VEToolchain.cpp b/clang/lib/Driver/ToolChains/VEToolchain.cpp
new file mode 100644
index 0000000000000..6ea405c0269c7
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/VEToolchain.cpp
@@ -0,0 +1,119 @@
+//===--- VE.cpp - VE 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 "VEToolchain.h"
+#include "CommonArgs.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/Options.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include <cstdlib> // ::getenv
+
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
+using namespace clang;
+using namespace llvm::opt;
+
+/// VE tool chain
+VEToolChain::VEToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : Linux(D, Triple, Args) {
+ 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.
+ getFilePaths().clear();
+ getFilePaths().push_back(getArchSpecificLibPath());
+ getFilePaths().push_back(computeSysRoot() + "/opt/nec/ve/lib");
+}
+
+Tool *VEToolChain::buildAssembler() const {
+ return new tools::gnutools::Assembler(*this);
+}
+
+Tool *VEToolChain::buildLinker() const {
+ return new tools::gnutools::Linker(*this);
+}
+
+bool VEToolChain::isPICDefault() const { return false; }
+
+bool VEToolChain::isPIEDefault() const { return false; }
+
+bool VEToolChain::isPICDefaultForced() const { return false; }
+
+bool VEToolChain::SupportsProfiling() const { return false; }
+
+bool VEToolChain::hasBlocksRuntime() const { return false; }
+
+void VEToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
+ return;
+
+ if (DriverArgs.hasArg(options::OPT_nobuiltininc) &&
+ DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+ SmallString<128> P(getDriver().ResourceDir);
+ llvm::sys::path::append(P, "include");
+ addSystemInclude(DriverArgs, CC1Args, P);
+ }
+
+ if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
+ if (const char *cl_include_dir = getenv("NCC_C_INCLUDE_PATH")) {
+ SmallVector<StringRef, 4> Dirs;
+ const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
+ StringRef(cl_include_dir).split(Dirs, StringRef(EnvPathSeparatorStr));
+ ArrayRef<StringRef> DirVec(Dirs);
+ addSystemIncludes(DriverArgs, CC1Args, DirVec);
+ } else {
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/opt/nec/ve/include");
+ }
+ }
+}
+
+void VEToolChain::addClangTargetOptions(const ArgList &DriverArgs,
+ ArgStringList &CC1Args,
+ Action::OffloadKind) const {
+ CC1Args.push_back("-nostdsysteminc");
+ bool UseInitArrayDefault = true;
+ if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
+ options::OPT_fno_use_init_array, UseInitArrayDefault))
+ CC1Args.push_back("-fno-use-init-array");
+}
+
+void VEToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ // TODO upstream VE libc++ patches
+ llvm_unreachable("The VE target has no C++ stdlib for Clang yet");
+}
+
+void VEToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ // TODO upstream VE libc++ patches
+ llvm_unreachable("The VE target has no C++ stdlib for Clang yet");
+}
+
+llvm::ExceptionHandling
+VEToolChain::GetExceptionModel(const ArgList &Args) const {
+ // VE uses SjLj exceptions.
+ return llvm::ExceptionHandling::SjLj;
+}
diff --git a/clang/lib/Driver/ToolChains/VEToolchain.h b/clang/lib/Driver/ToolChains/VEToolchain.h
new file mode 100644
index 0000000000000..59069c0a75959
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/VEToolchain.h
@@ -0,0 +1,66 @@
+//===--- VE.h - VE 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_VE_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_VE_H
+
+#include "Linux.h"
+#include "clang/Driver/ToolChain.h"
+
+namespace clang {
+namespace driver {
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY VEToolChain : public Linux {
+public:
+ VEToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+protected:
+ Tool *buildAssembler() const override;
+ Tool *buildLinker() const override;
+
+public:
+ bool isPICDefault() const override;
+ bool isPIEDefault() const override;
+ bool isPICDefaultForced() const override;
+ bool SupportsProfiling() const override;
+ bool hasBlocksRuntime() 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;
+ void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+
+ llvm::ExceptionHandling
+ GetExceptionModel(const llvm::opt::ArgList &Args) const override;
+
+ CXXStdlibType
+ GetCXXStdlibType(const llvm::opt::ArgList &Args) const override {
+ return ToolChain::CST_Libcxx;
+ }
+
+ RuntimeLibType GetDefaultRuntimeLibType() const override {
+ return ToolChain::RLT_CompilerRT;
+ }
+
+ const char *getDefaultLinker() const override { return "nld"; }
+};
+
+} // end namespace toolchains
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_VE_H
diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp
index 907f86b8233c5..10168736400f8 100644
--- a/clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -40,7 +40,7 @@ std::string wasm::Linker::getLinkerPath(const ArgList &Args) const {
if (!UseLinker.empty()) {
if (llvm::sys::path::is_absolute(UseLinker) &&
llvm::sys::fs::can_execute(UseLinker))
- return UseLinker;
+ return std::string(UseLinker);
// Accept 'lld', and 'ld' as aliases for the default linker
if (UseLinker != "lld" && UseLinker != "ld")
@@ -62,6 +62,12 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const char *Linker = Args.MakeArgString(getLinkerPath(Args));
ArgStringList CmdArgs;
+ CmdArgs.push_back("-m");
+ if (getToolChain().getTriple().isArch64Bit())
+ CmdArgs.push_back("wasm64");
+ else
+ CmdArgs.push_back("wasm32");
+
if (Args.hasArg(options::OPT_s))
CmdArgs.push_back("--strip-all");
@@ -69,8 +75,26 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_u);
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
+ const char *Crt1 = "crt1.o";
+ const char *Entry = NULL;
+ if (const Arg *A = Args.getLastArg(options::OPT_mexec_model_EQ)) {
+ StringRef CM = A->getValue();
+ if (CM == "command") {
+ // Use default values.
+ } else if (CM == "reactor") {
+ Crt1 = "crt1-reactor.o";
+ Entry = "_initialize";
+ } else {
+ ToolChain.getDriver().Diag(diag::err_drv_invalid_argument_to_option)
+ << CM << A->getOption().getName();
+ }
+ }
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt1.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(Crt1)));
+ if (Entry) {
+ CmdArgs.push_back(Args.MakeArgString("--entry"));
+ CmdArgs.push_back(Args.MakeArgString(Entry));
+ }
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
@@ -90,7 +114,8 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- C.addCommand(std::make_unique<Command>(JA, *this, Linker, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Linker, CmdArgs, Inputs));
// When optimizing, if wasm-opt is available, run it.
if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
@@ -112,7 +137,9 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(llvm::Twine("-O") + OOpt));
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- C.addCommand(std::make_unique<Command>(JA, *this, WasmOpt, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), WasmOpt, CmdArgs,
+ Inputs));
}
}
}
@@ -283,7 +310,7 @@ void WebAssembly::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
CIncludeDirs.split(dirs, ":");
for (StringRef dir : dirs) {
StringRef Prefix =
- llvm::sys::path::is_absolute(dir) ? StringRef(D.SysRoot) : "";
+ llvm::sys::path::is_absolute(dir) ? "" : StringRef(D.SysRoot);
addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
}
return;
diff --git a/clang/lib/Driver/ToolChains/WebAssembly.h b/clang/lib/Driver/ToolChains/WebAssembly.h
index 67d5fce845765..616bfb5d3d0c1 100644
--- a/clang/lib/Driver/ToolChains/WebAssembly.h
+++ b/clang/lib/Driver/ToolChains/WebAssembly.h
@@ -18,10 +18,9 @@ namespace driver {
namespace tools {
namespace wasm {
-class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
- explicit Linker(const ToolChain &TC)
- : GnuTool("wasm::Linker", "linker", TC) {}
+ explicit Linker(const ToolChain &TC) : Tool("wasm::Linker", "linker", TC) {}
bool isLinkJob() const override { return true; }
bool hasIntegratedCPP() const override { return false; }
std::string getLinkerPath(const llvm::opt::ArgList &Args) const;
diff --git a/clang/lib/Driver/ToolChains/XCore.cpp b/clang/lib/Driver/ToolChains/XCore.cpp
index ba3a6d44addaf..5030c73c7d825 100644
--- a/clang/lib/Driver/ToolChains/XCore.cpp
+++ b/clang/lib/Driver/ToolChains/XCore.cpp
@@ -52,7 +52,8 @@ void tools::XCore::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(II.getFilename());
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc"));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Exec, CmdArgs, Inputs));
}
void tools::XCore::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -80,7 +81,8 @@ void tools::XCore::Linker::ConstructJob(Compilation &C, const JobAction &JA,
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc"));
- C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Exec, CmdArgs, Inputs));
}
/// XCore tool chain
diff --git a/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp
index 7d83be2521e73..399e26d8d64a6 100644
--- a/clang/lib/Driver/Types.cpp
+++ b/clang/lib/Driver/Types.cpp
@@ -24,10 +24,19 @@ struct TypeInfo {
const char *Name;
const char *TempSuffix;
ID PreprocessedType;
- const llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> Phases;
+ class PhasesBitSet {
+ unsigned Bits = 0;
+
+ public:
+ constexpr PhasesBitSet(std::initializer_list<phases::ID> Phases) {
+ for (auto Id : Phases)
+ Bits |= 1 << Id;
+ }
+ bool contains(phases::ID Id) const { return Bits & (1 << Id); }
+ } Phases;
};
-static const TypeInfo TypeInfos[] = {
+static constexpr TypeInfo TypeInfos[] = {
#define TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, ...) \
{ NAME, TEMP_SUFFIX, TY_##PP_TYPE, { __VA_ARGS__ }, },
#include "clang/Driver/Types.def"
@@ -46,18 +55,18 @@ const char *types::getTypeName(ID Id) {
types::ID types::getPreprocessedType(ID Id) {
ID PPT = getInfo(Id).PreprocessedType;
- assert((llvm::is_contained(getInfo(Id).Phases, phases::Preprocess) !=
+ assert((getInfo(Id).Phases.contains(phases::Preprocess) !=
(PPT == TY_INVALID)) &&
"Unexpected Preprocess Type.");
return PPT;
}
-static bool isPrepeocessedModuleType(ID Id) {
+static bool isPreprocessedModuleType(ID Id) {
return Id == TY_CXXModule || Id == TY_PP_CXXModule;
}
types::ID types::getPrecompiledType(ID Id) {
- if (isPrepeocessedModuleType(Id))
+ if (isPreprocessedModuleType(Id))
return TY_ModuleFile;
if (onlyPrecompileType(Id))
return TY_PCH;
@@ -81,15 +90,9 @@ const char *types::getTypeTempSuffix(ID Id, bool CLMode) {
return getInfo(Id).TempSuffix;
}
-bool types::onlyAssembleType(ID Id) {
- return llvm::is_contained(getInfo(Id).Phases, phases::Assemble) &&
- !llvm::is_contained(getInfo(Id).Phases, phases::Compile) &&
- !llvm::is_contained(getInfo(Id).Phases, phases::Backend);
-}
-
bool types::onlyPrecompileType(ID Id) {
- return llvm::is_contained(getInfo(Id).Phases, phases::Precompile) &&
- !isPrepeocessedModuleType(Id);
+ return getInfo(Id).Phases.contains(phases::Precompile) &&
+ !isPreprocessedModuleType(Id);
}
bool types::canTypeBeUserSpecified(ID Id) {
@@ -275,6 +278,7 @@ types::ID types::lookupTypeForExtension(llvm::StringRef Ext) {
.Case("gch", TY_PCH)
.Case("hip", TY_HIP)
.Case("hpp", TY_CXXHeader)
+ .Case("hxx", TY_CXXHeader)
.Case("iim", TY_PP_CXXModule)
.Case("lib", TY_Object)
.Case("mii", TY_PP_ObjCXX)
@@ -295,24 +299,28 @@ types::ID types::lookupTypeForTypeSpecifier(const char *Name) {
strcmp(Name, getInfo(Id).Name) == 0)
return Id;
}
-
+ // Accept "cu" as an alias for "cuda" for NVCC compatibility
+ if (strcmp(Name, "cu") == 0) {
+ return types::TY_CUDA;
+ }
return TY_INVALID;
}
-// FIXME: Why don't we just put this list in the defs file, eh.
-// FIXME: The list is now in Types.def but for now this function will verify
-// the old behavior and a subsequent change will delete most of the body.
-void types::getCompilationPhases(ID Id, llvm::SmallVectorImpl<phases::ID> &P) {
- P = getInfo(Id).Phases;
- assert(0 < P.size() && "Not enough phases in list");
+llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases>
+types::getCompilationPhases(ID Id, phases::ID LastPhase) {
+ llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> P;
+ const auto &Info = getInfo(Id);
+ for (int I = 0; I <= LastPhase; ++I)
+ if (Info.Phases.contains(static_cast<phases::ID>(I)))
+ P.push_back(static_cast<phases::ID>(I));
assert(P.size() <= phases::MaxNumberOfPhases && "Too many phases in list");
+ return P;
}
-void types::getCompilationPhases(const clang::driver::Driver &Driver,
- llvm::opt::DerivedArgList &DAL, ID Id,
- llvm::SmallVectorImpl<phases::ID> &P) {
- llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PhaseList;
- types::getCompilationPhases(Id, PhaseList);
+llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases>
+types::getCompilationPhases(const clang::driver::Driver &Driver,
+ llvm::opt::DerivedArgList &DAL, ID Id) {
+ phases::ID LastPhase;
// Filter to compiler mode. When the compiler is run as a preprocessor then
// compilation is not an option.
@@ -321,14 +329,12 @@ void types::getCompilationPhases(const clang::driver::Driver &Driver,
DAL.getLastArg(options::OPT__SLASH_EP) ||
DAL.getLastArg(options::OPT_M, options::OPT_MM) ||
DAL.getLastArg(options::OPT__SLASH_P))
- llvm::copy_if(PhaseList, std::back_inserter(P),
- [](phases::ID Phase) { return Phase <= phases::Preprocess; });
+ LastPhase = phases::Preprocess;
// --precompile only runs up to precompilation.
// This is a clang extension and is not compatible with GCC.
else if (DAL.getLastArg(options::OPT__precompile))
- llvm::copy_if(PhaseList, std::back_inserter(P),
- [](phases::ID Phase) { return Phase <= phases::Precompile; });
+ LastPhase = phases::Precompile;
// -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
else if (DAL.getLastArg(options::OPT_fsyntax_only) ||
@@ -340,21 +346,20 @@ void types::getCompilationPhases(const clang::driver::Driver &Driver,
DAL.getLastArg(options::OPT__migrate) ||
DAL.getLastArg(options::OPT__analyze) ||
DAL.getLastArg(options::OPT_emit_ast))
- llvm::copy_if(PhaseList, std::back_inserter(P),
- [](phases::ID Phase) { return Phase <= phases::Compile; });
+ LastPhase = phases::Compile;
else if (DAL.getLastArg(options::OPT_S) ||
DAL.getLastArg(options::OPT_emit_llvm))
- llvm::copy_if(PhaseList, std::back_inserter(P),
- [](phases::ID Phase) { return Phase <= phases::Backend; });
+ LastPhase = phases::Backend;
else if (DAL.getLastArg(options::OPT_c))
- llvm::copy_if(PhaseList, std::back_inserter(P),
- [](phases::ID Phase) { return Phase <= phases::Assemble; });
+ LastPhase = phases::Assemble;
// Generally means, do every phase until Link.
else
- P = PhaseList;
+ LastPhase = phases::LastPhase;
+
+ return types::getCompilationPhases(Id, LastPhase);
}
ID types::lookupCXXTypeForCType(ID Id) {
diff --git a/clang/lib/Driver/XRayArgs.cpp b/clang/lib/Driver/XRayArgs.cpp
index a2dd63f9eb77c..f00c3906df974 100644
--- a/clang/lib/Driver/XRayArgs.cpp
+++ b/clang/lib/Driver/XRayArgs.cpp
@@ -13,10 +13,10 @@
#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/SpecialCaseList.h"
+#include "llvm/Support/VirtualFileSystem.h"
using namespace clang;
using namespace clang::driver;
@@ -32,157 +32,163 @@ constexpr const char *const XRaySupportedModes[] = {"xray-fdr", "xray-basic"};
XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
const Driver &D = TC.getDriver();
const llvm::Triple &Triple = TC.getTriple();
- if (Args.hasFlag(options::OPT_fxray_instrument,
- options::OPT_fnoxray_instrument, false)) {
- if (Triple.getOS() == llvm::Triple::Linux) {
- switch (Triple.getArch()) {
- case llvm::Triple::x86_64:
- case llvm::Triple::arm:
- case llvm::Triple::aarch64:
- case llvm::Triple::ppc64le:
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- break;
- default:
- D.Diag(diag::err_drv_clang_unsupported)
- << (std::string(XRayInstrumentOption) + " on " + Triple.str());
- }
- } else if (Triple.isOSFreeBSD() ||
- Triple.isOSOpenBSD() ||
- Triple.isOSNetBSD() ||
- Triple.isMacOSX()) {
- if (Triple.getArch() != llvm::Triple::x86_64) {
- D.Diag(diag::err_drv_clang_unsupported)
- << (std::string(XRayInstrumentOption) + " on " + Triple.str());
- }
- } else if (Triple.getOS() == llvm::Triple::Fuchsia) {
- switch (Triple.getArch()) {
- case llvm::Triple::x86_64:
- case llvm::Triple::aarch64:
- break;
- default:
- D.Diag(diag::err_drv_clang_unsupported)
- << (std::string(XRayInstrumentOption) + " on " + Triple.str());
- }
- } else {
+ if (!Args.hasFlag(options::OPT_fxray_instrument,
+ options::OPT_fno_xray_instrument, false))
+ return;
+ if (Triple.getOS() == llvm::Triple::Linux) {
+ switch (Triple.getArch()) {
+ case llvm::Triple::x86_64:
+ case llvm::Triple::arm:
+ case llvm::Triple::aarch64:
+ case llvm::Triple::ppc64le:
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ break;
+ default:
D.Diag(diag::err_drv_clang_unsupported)
<< (std::string(XRayInstrumentOption) + " on " + Triple.str());
}
-
- // Both XRay and -fpatchable-function-entry use
- // TargetOpcode::PATCHABLE_FUNCTION_ENTER.
- if (Arg *A = Args.getLastArg(options::OPT_fpatchable_function_entry_EQ))
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << "-fxray-instrument" << A->getSpelling();
-
- XRayInstrument = true;
- if (const Arg *A =
- Args.getLastArg(options::OPT_fxray_instruction_threshold_,
- options::OPT_fxray_instruction_threshold_EQ)) {
- StringRef S = A->getValue();
- if (S.getAsInteger(0, InstructionThreshold) || InstructionThreshold < 0)
- D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
+ } else if (Triple.isOSFreeBSD() || Triple.isOSOpenBSD() ||
+ Triple.isOSNetBSD() || Triple.isMacOSX()) {
+ if (Triple.getArch() != llvm::Triple::x86_64) {
+ D.Diag(diag::err_drv_clang_unsupported)
+ << (std::string(XRayInstrumentOption) + " on " + Triple.str());
+ }
+ } else if (Triple.getOS() == llvm::Triple::Fuchsia) {
+ switch (Triple.getArch()) {
+ case llvm::Triple::x86_64:
+ case llvm::Triple::aarch64:
+ break;
+ default:
+ D.Diag(diag::err_drv_clang_unsupported)
+ << (std::string(XRayInstrumentOption) + " on " + Triple.str());
}
+ } else {
+ D.Diag(diag::err_drv_clang_unsupported)
+ << (std::string(XRayInstrumentOption) + " on " + Triple.str());
+ }
+
+ // Both XRay and -fpatchable-function-entry use
+ // TargetOpcode::PATCHABLE_FUNCTION_ENTER.
+ if (Arg *A = Args.getLastArg(options::OPT_fpatchable_function_entry_EQ))
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << "-fxray-instrument" << A->getSpelling();
+
+ XRayInstrument = true;
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_fxray_instruction_threshold_,
+ options::OPT_fxray_instruction_threshold_EQ)) {
+ StringRef S = A->getValue();
+ if (S.getAsInteger(0, InstructionThreshold) || InstructionThreshold < 0)
+ D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
+ }
+
+ // By default, the back-end will not emit the lowering for XRay customevent
+ // calls if the function is not instrumented. In the future we will change
+ // this default to be the reverse, but in the meantime we're going to
+ // introduce the new functionality behind a flag.
+ if (Args.hasFlag(options::OPT_fxray_always_emit_customevents,
+ options::OPT_fno_xray_always_emit_customevents, false))
+ XRayAlwaysEmitCustomEvents = true;
+
+ if (Args.hasFlag(options::OPT_fxray_always_emit_typedevents,
+ options::OPT_fno_xray_always_emit_typedevents, false))
+ XRayAlwaysEmitTypedEvents = true;
+
+ if (!Args.hasFlag(options::OPT_fxray_link_deps,
+ options::OPT_fnoxray_link_deps, true))
+ XRayRT = false;
- // By default, the back-end will not emit the lowering for XRay customevent
- // calls if the function is not instrumented. In the future we will change
- // this default to be the reverse, but in the meantime we're going to
- // introduce the new functionality behind a flag.
- if (Args.hasFlag(options::OPT_fxray_always_emit_customevents,
- options::OPT_fnoxray_always_emit_customevents, false))
- XRayAlwaysEmitCustomEvents = true;
-
- if (Args.hasFlag(options::OPT_fxray_always_emit_typedevents,
- options::OPT_fnoxray_always_emit_typedevents, false))
- XRayAlwaysEmitTypedEvents = true;
-
- if (!Args.hasFlag(options::OPT_fxray_link_deps,
- options::OPT_fnoxray_link_deps, true))
- XRayRT = false;
-
- auto Bundles =
- Args.getAllArgValues(options::OPT_fxray_instrumentation_bundle);
- if (Bundles.empty())
- InstrumentationBundle.Mask = XRayInstrKind::All;
- else
- for (const auto &B : Bundles) {
- llvm::SmallVector<StringRef, 2> BundleParts;
- llvm::SplitString(B, BundleParts, ",");
- for (const auto &P : BundleParts) {
- // TODO: Automate the generation of the string case table.
- auto Valid = llvm::StringSwitch<bool>(P)
- .Cases("none", "all", "function", "custom", true)
- .Default(false);
-
- if (!Valid) {
- D.Diag(clang::diag::err_drv_invalid_value)
- << "-fxray-instrumentation-bundle=" << P;
- continue;
- }
-
- auto Mask = parseXRayInstrValue(P);
- if (Mask == XRayInstrKind::None) {
- InstrumentationBundle.clear();
- break;
- }
-
- InstrumentationBundle.Mask |= Mask;
+ if (Args.hasFlag(options::OPT_fxray_ignore_loops,
+ options::OPT_fno_xray_ignore_loops, false))
+ XRayIgnoreLoops = true;
+
+ XRayFunctionIndex = Args.hasFlag(options::OPT_fxray_function_index,
+ options::OPT_fno_xray_function_index, true);
+
+ auto Bundles =
+ Args.getAllArgValues(options::OPT_fxray_instrumentation_bundle);
+ if (Bundles.empty())
+ InstrumentationBundle.Mask = XRayInstrKind::All;
+ else
+ for (const auto &B : Bundles) {
+ llvm::SmallVector<StringRef, 2> BundleParts;
+ llvm::SplitString(B, BundleParts, ",");
+ for (const auto &P : BundleParts) {
+ // TODO: Automate the generation of the string case table.
+ auto Valid = llvm::StringSwitch<bool>(P)
+ .Cases("none", "all", "function", "function-entry",
+ "function-exit", "custom", true)
+ .Default(false);
+
+ if (!Valid) {
+ D.Diag(clang::diag::err_drv_invalid_value)
+ << "-fxray-instrumentation-bundle=" << P;
+ continue;
}
- }
- // Validate the always/never attribute files. We also make sure that they
- // are treated as actual dependencies.
- for (const auto &Filename :
- Args.getAllArgValues(options::OPT_fxray_always_instrument)) {
- if (D.getVFS().exists(Filename)) {
- AlwaysInstrumentFiles.push_back(Filename);
- ExtraDeps.push_back(Filename);
- } else
- D.Diag(clang::diag::err_drv_no_such_file) << Filename;
- }
+ auto Mask = parseXRayInstrValue(P);
+ if (Mask == XRayInstrKind::None) {
+ InstrumentationBundle.clear();
+ break;
+ }
- for (const auto &Filename :
- Args.getAllArgValues(options::OPT_fxray_never_instrument)) {
- if (D.getVFS().exists(Filename)) {
- NeverInstrumentFiles.push_back(Filename);
- ExtraDeps.push_back(Filename);
- } else
- D.Diag(clang::diag::err_drv_no_such_file) << Filename;
+ InstrumentationBundle.Mask |= Mask;
+ }
}
- for (const auto &Filename :
- Args.getAllArgValues(options::OPT_fxray_attr_list)) {
- if (D.getVFS().exists(Filename)) {
- AttrListFiles.push_back(Filename);
- ExtraDeps.push_back(Filename);
- } else
- D.Diag(clang::diag::err_drv_no_such_file) << Filename;
- }
+ // Validate the always/never attribute files. We also make sure that they
+ // are treated as actual dependencies.
+ for (const auto &Filename :
+ Args.getAllArgValues(options::OPT_fxray_always_instrument)) {
+ if (D.getVFS().exists(Filename)) {
+ AlwaysInstrumentFiles.push_back(Filename);
+ ExtraDeps.push_back(Filename);
+ } else
+ D.Diag(clang::diag::err_drv_no_such_file) << Filename;
+ }
- // Get the list of modes we want to support.
- auto SpecifiedModes = Args.getAllArgValues(options::OPT_fxray_modes);
- if (SpecifiedModes.empty())
- llvm::copy(XRaySupportedModes, std::back_inserter(Modes));
- else
- for (const auto &Arg : SpecifiedModes) {
- // Parse CSV values for -fxray-modes=...
- llvm::SmallVector<StringRef, 2> ModeParts;
- llvm::SplitString(Arg, ModeParts, ",");
- for (const auto &M : ModeParts)
- if (M == "none")
- Modes.clear();
- else if (M == "all")
- llvm::copy(XRaySupportedModes, std::back_inserter(Modes));
- else
- Modes.push_back(M);
- }
+ for (const auto &Filename :
+ Args.getAllArgValues(options::OPT_fxray_never_instrument)) {
+ if (D.getVFS().exists(Filename)) {
+ NeverInstrumentFiles.push_back(Filename);
+ ExtraDeps.push_back(Filename);
+ } else
+ D.Diag(clang::diag::err_drv_no_such_file) << Filename;
+ }
- // Then we want to sort and unique the modes we've collected.
- llvm::sort(Modes);
- Modes.erase(std::unique(Modes.begin(), Modes.end()), Modes.end());
+ for (const auto &Filename :
+ Args.getAllArgValues(options::OPT_fxray_attr_list)) {
+ if (D.getVFS().exists(Filename)) {
+ AttrListFiles.push_back(Filename);
+ ExtraDeps.push_back(Filename);
+ } else
+ D.Diag(clang::diag::err_drv_no_such_file) << Filename;
}
+
+ // Get the list of modes we want to support.
+ auto SpecifiedModes = Args.getAllArgValues(options::OPT_fxray_modes);
+ if (SpecifiedModes.empty())
+ llvm::copy(XRaySupportedModes, std::back_inserter(Modes));
+ else
+ for (const auto &Arg : SpecifiedModes) {
+ // Parse CSV values for -fxray-modes=...
+ llvm::SmallVector<StringRef, 2> ModeParts;
+ llvm::SplitString(Arg, ModeParts, ",");
+ for (const auto &M : ModeParts)
+ if (M == "none")
+ Modes.clear();
+ else if (M == "all")
+ llvm::copy(XRaySupportedModes, std::back_inserter(Modes));
+ else
+ Modes.push_back(std::string(M));
+ }
+
+ // Then we want to sort and unique the modes we've collected.
+ llvm::sort(Modes);
+ Modes.erase(std::unique(Modes.begin(), Modes.end()), Modes.end());
}
void XRayArgs::addArgs(const ToolChain &TC, const ArgList &Args,
@@ -198,6 +204,12 @@ void XRayArgs::addArgs(const ToolChain &TC, const ArgList &Args,
if (XRayAlwaysEmitTypedEvents)
CmdArgs.push_back("-fxray-always-emit-typedevents");
+ if (XRayIgnoreLoops)
+ CmdArgs.push_back("-fxray-ignore-loops");
+
+ if (!XRayFunctionIndex)
+ CmdArgs.push_back("-fno-xray-function-index");
+
CmdArgs.push_back(Args.MakeArgString(Twine(XRayInstructionThresholdOption) +
Twine(InstructionThreshold)));
@@ -237,8 +249,14 @@ void XRayArgs::addArgs(const ToolChain &TC, const ArgList &Args,
} else if (InstrumentationBundle.empty()) {
Bundle += "none";
} else {
- if (InstrumentationBundle.has(XRayInstrKind::Function))
+ if (InstrumentationBundle.has(XRayInstrKind::FunctionEntry) &&
+ InstrumentationBundle.has(XRayInstrKind::FunctionExit))
Bundle += "function";
+ else if (InstrumentationBundle.has(XRayInstrKind::FunctionEntry))
+ Bundle += "function-entry";
+ else if (InstrumentationBundle.has(XRayInstrKind::FunctionExit))
+ Bundle += "function-exit";
+
if (InstrumentationBundle.has(XRayInstrKind::Custom))
Bundle += "custom";
if (InstrumentationBundle.has(XRayInstrKind::Typed))