summaryrefslogtreecommitdiff
path: root/clang/lib/Driver
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2020-01-17 20:45:01 +0000
committerDimitry Andric <dim@FreeBSD.org>2020-01-17 20:45:01 +0000
commit706b4fc47bbc608932d3b491ae19a3b9cde9497b (patch)
tree4adf86a776049cbf7f69a1929c4babcbbef925eb /clang/lib/Driver
parent7cc9cf2bf09f069cb2dd947ead05d0b54301fb71 (diff)
Notes
Diffstat (limited to 'clang/lib/Driver')
-rw-r--r--clang/lib/Driver/Distro.cpp23
-rw-r--r--clang/lib/Driver/Driver.cpp149
-rw-r--r--clang/lib/Driver/Job.cpp108
-rw-r--r--clang/lib/Driver/OptionUtils.cpp47
-rw-r--r--clang/lib/Driver/SanitizerArgs.cpp32
-rw-r--r--clang/lib/Driver/ToolChain.cpp26
-rw-r--r--clang/lib/Driver/ToolChains/AIX.cpp159
-rw-r--r--clang/lib/Driver/ToolChains/AIX.h75
-rw-r--r--clang/lib/Driver/ToolChains/AMDGPU.h2
-rw-r--r--clang/lib/Driver/ToolChains/Arch/AArch64.cpp9
-rw-r--r--clang/lib/Driver/ToolChains/Arch/ARM.cpp47
-rw-r--r--clang/lib/Driver/ToolChains/Arch/PPC.cpp6
-rw-r--r--clang/lib/Driver/ToolChains/Arch/RISCV.cpp203
-rw-r--r--clang/lib/Driver/ToolChains/Arch/RISCV.h2
-rw-r--r--clang/lib/Driver/ToolChains/Arch/SystemZ.cpp18
-rw-r--r--clang/lib/Driver/ToolChains/Arch/SystemZ.h3
-rw-r--r--clang/lib/Driver/ToolChains/Arch/X86.cpp3
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp866
-rw-r--r--clang/lib/Driver/ToolChains/CommonArgs.cpp141
-rw-r--r--clang/lib/Driver/ToolChains/CommonArgs.h11
-rw-r--r--clang/lib/Driver/ToolChains/Cuda.cpp3
-rw-r--r--clang/lib/Driver/ToolChains/Darwin.cpp105
-rw-r--r--clang/lib/Driver/ToolChains/Darwin.h10
-rw-r--r--clang/lib/Driver/ToolChains/Flang.cpp79
-rw-r--r--clang/lib/Driver/ToolChains/Flang.h46
-rw-r--r--clang/lib/Driver/ToolChains/FreeBSD.cpp38
-rw-r--r--clang/lib/Driver/ToolChains/FreeBSD.h7
-rw-r--r--clang/lib/Driver/ToolChains/Fuchsia.cpp25
-rw-r--r--clang/lib/Driver/ToolChains/Gnu.cpp215
-rw-r--r--clang/lib/Driver/ToolChains/Gnu.h9
-rw-r--r--clang/lib/Driver/ToolChains/HIP.cpp80
-rw-r--r--clang/lib/Driver/ToolChains/HIP.h2
-rw-r--r--clang/lib/Driver/ToolChains/Hexagon.cpp13
-rw-r--r--clang/lib/Driver/ToolChains/Hurd.cpp10
-rw-r--r--clang/lib/Driver/ToolChains/Hurd.h4
-rw-r--r--clang/lib/Driver/ToolChains/InterfaceStubs.cpp38
-rw-r--r--clang/lib/Driver/ToolChains/Linux.cpp76
-rw-r--r--clang/lib/Driver/ToolChains/Linux.h7
-rw-r--r--clang/lib/Driver/ToolChains/MSVC.cpp22
-rw-r--r--clang/lib/Driver/ToolChains/MinGW.cpp14
-rw-r--r--clang/lib/Driver/ToolChains/NetBSD.cpp6
-rw-r--r--clang/lib/Driver/ToolChains/OpenBSD.cpp9
-rw-r--r--clang/lib/Driver/ToolChains/OpenBSD.h5
-rw-r--r--clang/lib/Driver/ToolChains/PS4CPU.h4
-rw-r--r--clang/lib/Driver/ToolChains/RISCVToolchain.cpp92
-rw-r--r--clang/lib/Driver/ToolChains/RISCVToolchain.h4
-rw-r--r--clang/lib/Driver/ToolChains/WebAssembly.cpp64
-rw-r--r--clang/lib/Driver/Types.cpp26
-rw-r--r--clang/lib/Driver/XRayArgs.cpp13
49 files changed, 2309 insertions, 647 deletions
diff --git a/clang/lib/Driver/Distro.cpp b/clang/lib/Driver/Distro.cpp
index f2a3074d1e701..06707fefc9d08 100644
--- a/clang/lib/Driver/Distro.cpp
+++ b/clang/lib/Driver/Distro.cpp
@@ -13,11 +13,28 @@
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/ADT/Triple.h"
using namespace clang::driver;
using namespace clang;
-static Distro::DistroType DetectDistro(llvm::vfs::FileSystem &VFS) {
+static Distro::DistroType DetectDistro(llvm::vfs::FileSystem &VFS,
+ const llvm::Triple &TargetOrHost) {
+ // If we don't target Linux, no need to check the distro. This saves a few
+ // OS calls.
+ if (!TargetOrHost.isOSLinux())
+ return Distro::UnknownDistro;
+
+ // If the host is not running Linux, and we're backed by a real file system,
+ // no need to check the distro. This is the case where someone is
+ // cross-compiling from BSD or Windows to Linux, and it would be meaningless
+ // to try to figure out the "distro" of the non-Linux host.
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> RealFS =
+ llvm::vfs::getRealFileSystem();
+ llvm::Triple HostTriple(llvm::sys::getProcessTriple());
+ if (!HostTriple.isOSLinux() && &VFS == RealFS.get())
+ return Distro::UnknownDistro;
+
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
VFS.getBufferForFile("/etc/lsb-release");
if (File) {
@@ -52,6 +69,7 @@ static Distro::DistroType DetectDistro(llvm::vfs::FileSystem &VFS) {
.Case("cosmic", Distro::UbuntuCosmic)
.Case("disco", Distro::UbuntuDisco)
.Case("eoan", Distro::UbuntuEoan)
+ .Case("focal", Distro::UbuntuFocal)
.Default(Distro::UnknownDistro);
if (Version != Distro::UnknownDistro)
return Version;
@@ -148,4 +166,5 @@ static Distro::DistroType DetectDistro(llvm::vfs::FileSystem &VFS) {
return Distro::UnknownDistro;
}
-Distro::Distro(llvm::vfs::FileSystem &VFS) : DistroVal(DetectDistro(VFS)) {}
+Distro::Distro(llvm::vfs::FileSystem &VFS, const llvm::Triple &TargetOrHost)
+ : DistroVal(DetectDistro(VFS, TargetOrHost)) {}
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index f6016b43b6920..e718b8366df0e 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -8,6 +8,7 @@
#include "clang/Driver/Driver.h"
#include "InputInfo.h"
+#include "ToolChains/AIX.h"
#include "ToolChains/AMDGPU.h"
#include "ToolChains/AVR.h"
#include "ToolChains/Ananas.h"
@@ -177,6 +178,7 @@ void Driver::setDriverModeFromOption(StringRef Opt) {
.Case("g++", GXXMode)
.Case("cpp", CPPMode)
.Case("cl", CLMode)
+ .Case("flang", FlangMode)
.Default(None))
Mode = *M;
else
@@ -290,10 +292,6 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
(PhaseArg = DAL.getLastArg(options::OPT_emit_ast))) {
FinalPhase = phases::Compile;
- // clang interface stubs
- } else if ((PhaseArg = DAL.getLastArg(options::OPT_emit_interface_stubs))) {
- FinalPhase = phases::IfsMerge;
-
// -S only runs up to the backend.
} else if ((PhaseArg = DAL.getLastArg(options::OPT_S))) {
FinalPhase = phases::Backend;
@@ -539,6 +537,17 @@ static llvm::Triple computeTargetTriple(const Driver &D,
}
}
+ // If target is RISC-V adjust the target triple according to
+ // provided architecture name
+ A = Args.getLastArg(options::OPT_march_EQ);
+ if (A && Target.isRISCV()) {
+ StringRef ArchName = A->getValue();
+ if (ArchName.startswith_lower("rv32"))
+ Target.setArch(llvm::Triple::riscv32);
+ else if (ArchName.startswith_lower("rv64"))
+ Target.setArch(llvm::Triple::riscv64);
+ }
+
return Target;
}
@@ -735,7 +744,7 @@ static bool searchForFile(SmallVectorImpl<char> &FilePath,
ArrayRef<std::string> Dirs,
StringRef FileName) {
SmallString<128> WPath;
- for (const StringRef &Dir : Dirs) {
+ for (const std::string &Dir : Dirs) {
if (Dir.empty())
continue;
WPath.clear();
@@ -1981,8 +1990,9 @@ void Driver::BuildUniversalActions(Compilation &C, const ToolChain &TC,
// Handle debug info queries.
Arg *A = Args.getLastArg(options::OPT_g_Group);
- if (A && !A->getOption().matches(options::OPT_g0) &&
- !A->getOption().matches(options::OPT_gstabs) &&
+ bool enablesDebugInfo = A && !A->getOption().matches(options::OPT_g0) &&
+ !A->getOption().matches(options::OPT_gstabs);
+ if ((enablesDebugInfo || willEmitRemarks(Args)) &&
ContainsCompileOrAssembleAction(Actions.back())) {
// Add a 'dsymutil' step if necessary, when debug info is enabled and we
@@ -3489,6 +3499,68 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
Actions.push_back(
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);
+ }
+
+ ActionList MergerInputs;
+
+ for (auto &I : Inputs) {
+ types::ID InputType = I.first;
+ const Arg *InputArg = I.second;
+
+ // Currently clang and the llvm assembler do not support generating symbol
+ // stubs from assembly, so we skip the input on asm files. For ifs files
+ // we rely on the normal pipeline setup in the pipeline setup code above.
+ if (InputType == types::TY_IFS || InputType == types::TY_PP_Asm ||
+ InputType == types::TY_Asm)
+ continue;
+
+ Action *Current = C.MakeAction<InputAction>(*InputArg, InputType);
+
+ for (auto Phase : PhaseList) {
+ switch (Phase) {
+ default:
+ llvm_unreachable(
+ "IFS Pipeline can only consist of Compile followed by IfsMerge.");
+ case phases::Compile: {
+ // Only IfsMerge (llvm-ifs) can handle .o files by looking for ifs
+ // files where the .o file is located. The compile action can not
+ // handle this.
+ if (InputType == types::TY_Object)
+ break;
+
+ Current = C.MakeAction<CompileJobAction>(Current, types::TY_IFS_CPP);
+ break;
+ }
+ case phases::IfsMerge: {
+ assert(Phase == PhaseList.back() &&
+ "merging must be final compilation step.");
+ MergerInputs.push_back(Current);
+ Current = nullptr;
+ break;
+ }
+ }
+ }
+
+ // If we ended with something, add to the output list.
+ if (Current)
+ Actions.push_back(Current);
+ }
+
+ // Add an interface stubs merge action if necessary.
+ if (!MergerInputs.empty())
+ Actions.push_back(
+ C.MakeAction<IfsMergeJobAction>(MergerInputs, types::TY_Image));
+ }
+
// If --print-supported-cpus, -mcpu=? or -mtune=? is specified, build a custom
// Compile phase that prints out supported cpu models and quits.
if (Arg *A = Args.getLastArg(options::OPT_print_supported_cpus)) {
@@ -3590,8 +3662,6 @@ Action *Driver::ConstructPhaseAction(
return C.MakeAction<CompileJobAction>(Input, types::TY_ModuleFile);
if (Args.hasArg(options::OPT_verify_pch))
return C.MakeAction<VerifyPCHJobAction>(Input, types::TY_Nothing);
- if (Args.hasArg(options::OPT_emit_interface_stubs))
- return C.MakeAction<CompileJobAction>(Input, types::TY_IFS_CPP);
return C.MakeAction<CompileJobAction>(Input, types::TY_LLVM_BC);
}
case phases::Backend: {
@@ -3620,11 +3690,29 @@ void Driver::BuildJobs(Compilation &C) const {
Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o);
// It is an error to provide a -o option if we are making multiple output
- // files.
+ // files. There are exceptions:
+ //
+ // IfsMergeJob: when generating interface stubs enabled we want to be able to
+ // generate the stub file at the same time that we generate the real
+ // library/a.out. So when a .o, .so, etc are the output, with clang interface
+ // stubs there will also be a .ifs and .ifso at the same location.
+ //
+ // CompileJob of type TY_IFS_CPP: when generating interface stubs is enabled
+ // and -c is passed, we still want to be able to generate a .ifs file while
+ // we are also generating .o files. So we allow more than one output file in
+ // this case as well.
+ //
if (FinalOutput) {
unsigned NumOutputs = 0;
+ unsigned NumIfsOutputs = 0;
for (const Action *A : C.getActions())
- if (A->getType() != types::TY_Nothing)
+ if (A->getType() != types::TY_Nothing &&
+ !(A->getKind() == Action::IfsMergeJobClass ||
+ (A->getType() == clang::driver::types::TY_IFS_CPP &&
+ A->getKind() == clang::driver::Action::CompileJobClass &&
+ 0 == NumIfsOutputs++) ||
+ (A->getKind() == Action::BindArchClass && A->getInputs().size() &&
+ A->getInputs().front()->getKind() == Action::IfsMergeJobClass)))
++NumOutputs;
if (NumOutputs > 1) {
@@ -4699,6 +4787,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
auto &TC = ToolChains[Target.str()];
if (!TC) {
switch (Target.getOS()) {
+ case llvm::Triple::AIX:
+ TC = std::make_unique<toolchains::AIX>(*this, Target, Args);
+ break;
case llvm::Triple::Haiku:
TC = std::make_unique<toolchains::Haiku>(*this, Target, Args);
break;
@@ -4872,6 +4963,19 @@ bool Driver::ShouldUseClangCompiler(const JobAction &JA) const {
return true;
}
+bool Driver::ShouldUseFlangCompiler(const JobAction &JA) const {
+ // Say "no" if there is not exactly one input of a type flang understands.
+ if (JA.size() != 1 ||
+ !types::isFortran((*JA.input_begin())->getType()))
+ return false;
+
+ // And say "no" if this is not a kind of action flang understands.
+ if (!isa<PreprocessJobAction>(JA) && !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA))
+ return false;
+
+ return true;
+}
+
/// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and return the
/// grouped values as integers. Numbers which are not provided are set to 0.
///
@@ -4957,3 +5061,26 @@ Driver::getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const {
bool clang::driver::isOptimizationLevelFast(const ArgList &Args) {
return Args.hasFlag(options::OPT_Ofast, options::OPT_O_Group, false);
}
+
+bool clang::driver::willEmitRemarks(const ArgList &Args) {
+ // -fsave-optimization-record enables it.
+ if (Args.hasFlag(options::OPT_fsave_optimization_record,
+ options::OPT_fno_save_optimization_record, false))
+ return true;
+
+ // -fsave-optimization-record=<format> enables it as well.
+ if (Args.hasFlag(options::OPT_fsave_optimization_record_EQ,
+ options::OPT_fno_save_optimization_record, false))
+ return true;
+
+ // -foptimization-record-file alone enables it too.
+ if (Args.hasFlag(options::OPT_foptimization_record_file_EQ,
+ options::OPT_fno_save_optimization_record, false))
+ return true;
+
+ // -foptimization-record-passes alone enables it too.
+ if (Args.hasFlag(options::OPT_foptimization_record_passes_EQ,
+ options::OPT_fno_save_optimization_record, false))
+ return true;
+ return false;
+}
diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp
index 0a95e49694f95..d57c3a1cdbb89 100644
--- a/clang/lib/Driver/Job.cpp
+++ b/clang/lib/Driver/Job.cpp
@@ -19,8 +19,10 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -313,15 +315,46 @@ void Command::setEnvironment(llvm::ArrayRef<const char *> NewEnvironment) {
Environment.push_back(nullptr);
}
-int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
- std::string *ErrMsg, bool *ExecutionFailed) const {
+void Command::PrintFileNames() const {
if (PrintInputFilenames) {
for (const char *Arg : InputFilenames)
llvm::outs() << llvm::sys::path::filename(Arg) << "\n";
llvm::outs().flush();
}
+}
- SmallVector<const char*, 128> Argv;
+int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
+ std::string *ErrMsg, bool *ExecutionFailed) const {
+ PrintFileNames();
+
+ SmallVector<const char *, 128> Argv;
+ if (ResponseFile == nullptr) {
+ Argv.push_back(Executable);
+ Argv.append(Arguments.begin(), Arguments.end());
+ Argv.push_back(nullptr);
+ } else {
+ // If the command is too large, we need to put arguments in a response file.
+ std::string RespContents;
+ llvm::raw_string_ostream SS(RespContents);
+
+ // Write file contents and build the Argv vector
+ writeResponseFile(SS);
+ buildArgvForResponseFile(Argv);
+ Argv.push_back(nullptr);
+ SS.flush();
+
+ // Save the response file in the appropriate encoding
+ if (std::error_code EC = writeFileWithEncoding(
+ ResponseFile, RespContents, Creator.getResponseFileEncoding())) {
+ if (ErrMsg)
+ *ErrMsg = EC.message();
+ if (ExecutionFailed)
+ *ExecutionFailed = true;
+ // Return -1 by convention (see llvm/include/llvm/Support/Program.h) to
+ // indicate the requested executable cannot be started.
+ return -1;
+ }
+ }
Optional<ArrayRef<StringRef>> Env;
std::vector<StringRef> ArgvVectorStorage;
@@ -332,42 +365,51 @@ int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
Env = makeArrayRef(ArgvVectorStorage);
}
- if (ResponseFile == nullptr) {
- Argv.push_back(Executable);
- Argv.append(Arguments.begin(), Arguments.end());
- Argv.push_back(nullptr);
+ auto Args = llvm::toStringRefArray(Argv.data());
+ return llvm::sys::ExecuteAndWait(Executable, Args, Env, Redirects,
+ /*secondsToWait*/ 0,
+ /*memoryLimit*/ 0, ErrMsg, ExecutionFailed);
+}
- auto Args = llvm::toStringRefArray(Argv.data());
- return llvm::sys::ExecuteAndWait(
- Executable, Args, Env, Redirects, /*secondsToWait*/ 0,
- /*memoryLimit*/ 0, ErrMsg, ExecutionFailed);
- }
+void CC1Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
+ CrashReportInfo *CrashInfo) const {
+ OS << " (in-process)";
+ Command::Print(OS, Terminator, Quote, CrashInfo);
+}
- // We need to put arguments in a response file (command is too large)
- // Open stream to store the response file contents
- std::string RespContents;
- llvm::raw_string_ostream SS(RespContents);
+int CC1Command::Execute(ArrayRef<llvm::Optional<StringRef>> /*Redirects*/,
+ std::string *ErrMsg, bool *ExecutionFailed) const {
+ PrintFileNames();
- // Write file contents and build the Argv vector
- writeResponseFile(SS);
- buildArgvForResponseFile(Argv);
+ SmallVector<const char *, 128> Argv;
+ Argv.push_back(getExecutable());
+ Argv.append(getArguments().begin(), getArguments().end());
Argv.push_back(nullptr);
- SS.flush();
-
- // Save the response file in the appropriate encoding
- if (std::error_code EC = writeFileWithEncoding(
- ResponseFile, RespContents, Creator.getResponseFileEncoding())) {
- if (ErrMsg)
- *ErrMsg = EC.message();
- if (ExecutionFailed)
- *ExecutionFailed = true;
- return -1;
+
+ // This flag simply indicates that the program couldn't start, which isn't
+ // applicable here.
+ if (ExecutionFailed)
+ *ExecutionFailed = false;
+
+ llvm::CrashRecoveryContext CRC;
+ CRC.DumpStackAndCleanupOnFailure = true;
+
+ const void *PrettyState = llvm::SavePrettyStackState();
+ const Driver &D = getCreator().getToolChain().getDriver();
+
+ int R = 0;
+ // Enter ExecuteCC1Tool() instead of starting up a new process
+ if (!CRC.RunSafely([&]() { R = D.CC1Main(Argv); })) {
+ llvm::RestorePrettyStackState(PrettyState);
+ return CRC.RetCode;
}
+ return R;
+}
- auto Args = llvm::toStringRefArray(Argv.data());
- return llvm::sys::ExecuteAndWait(Executable, Args, Env, Redirects,
- /*secondsToWait*/ 0,
- /*memoryLimit*/ 0, ErrMsg, ExecutionFailed);
+void CC1Command::setEnvironment(llvm::ArrayRef<const char *> NewEnvironment) {
+ // We don't support set a new environment when calling into ExecuteCC1Tool()
+ llvm_unreachable(
+ "The CC1Command doesn't support changing the environment vars!");
}
FallbackCommand::FallbackCommand(const Action &Source_, const Tool &Creator_,
diff --git a/clang/lib/Driver/OptionUtils.cpp b/clang/lib/Driver/OptionUtils.cpp
new file mode 100644
index 0000000000000..1f36ffc03cab3
--- /dev/null
+++ b/clang/lib/Driver/OptionUtils.cpp
@@ -0,0 +1,47 @@
+//===--- OptionUtils.cpp - Utilities for command line arguments -----------===//
+//
+// 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 "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticDriver.h"
+#include "clang/Driver/OptionUtils.h"
+#include "llvm/Option/ArgList.h"
+
+using namespace clang;
+using namespace llvm::opt;
+
+namespace {
+template <typename IntTy>
+IntTy getLastArgIntValueImpl(const ArgList &Args, OptSpecifier Id,
+ IntTy Default, DiagnosticsEngine *Diags,
+ unsigned Base) {
+ IntTy Res = Default;
+ if (Arg *A = Args.getLastArg(Id)) {
+ if (StringRef(A->getValue()).getAsInteger(Base, Res)) {
+ if (Diags)
+ Diags->Report(diag::err_drv_invalid_int_value)
+ << A->getAsString(Args) << A->getValue();
+ }
+ }
+ return Res;
+}
+} // namespace
+
+namespace clang {
+
+int getLastArgIntValue(const ArgList &Args, OptSpecifier Id, int Default,
+ DiagnosticsEngine *Diags, unsigned Base) {
+ return getLastArgIntValueImpl<int>(Args, Id, Default, Diags, Base);
+}
+
+uint64_t getLastArgUInt64Value(const ArgList &Args, OptSpecifier Id,
+ uint64_t Default, DiagnosticsEngine *Diags,
+ unsigned Base) {
+ return getLastArgIntValueImpl<uint64_t>(Args, Id, Default, Diags, Base);
+}
+
+} // namespace clang
diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp
index cc6c5e6ef438d..ac9a294ee3fa4 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -141,7 +141,7 @@ static void addDefaultBlacklists(const Driver &D, SanitizerMask Kinds,
clang::SmallString<64> Path(D.ResourceDir);
llvm::sys::path::append(Path, "share", BL.File);
- if (llvm::sys::fs::exists(Path))
+ if (D.getVFS().exists(Path))
BlacklistFiles.push_back(Path.str());
else if (BL.Mask == SanitizerKind::CFI)
// If cfi_blacklist.txt cannot be found in the resource dir, driver
@@ -557,29 +557,35 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// Setup blacklist files.
// Add default blacklist from resource directory.
- addDefaultBlacklists(D, Kinds, BlacklistFiles);
+ 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 (llvm::sys::fs::exists(BLPath)) {
- BlacklistFiles.push_back(BLPath);
- ExtraDeps.push_back(BLPath);
+ 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();
- BlacklistFiles.clear();
- ExtraDeps.clear();
+ UserBlacklistFiles.clear();
+ SystemBlacklistFiles.clear();
}
}
// Validate blacklists format.
{
std::string BLError;
std::unique_ptr<llvm::SpecialCaseList> SCL(
- llvm::SpecialCaseList::create(BlacklistFiles, BLError));
+ 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;
}
@@ -952,15 +958,15 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
CmdArgs.push_back(
Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));
- for (const auto &BLPath : BlacklistFiles) {
+ for (const auto &BLPath : UserBlacklistFiles) {
SmallString<64> BlacklistOpt("-fsanitize-blacklist=");
BlacklistOpt += BLPath;
CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
}
- for (const auto &Dep : ExtraDeps) {
- SmallString<64> ExtraDepOpt("-fdepfile-entry=");
- ExtraDepOpt += Dep;
- CmdArgs.push_back(Args.MakeArgString(ExtraDepOpt));
+ for (const auto &BLPath : SystemBlacklistFiles) {
+ SmallString<64> BlacklistOpt("-fsanitize-system-blacklist=");
+ BlacklistOpt += BLPath;
+ CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
}
if (MsanTrackOrigins)
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 357a5106ab393..3ebbd30195b31 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -11,6 +11,7 @@
#include "ToolChains/Arch/ARM.h"
#include "ToolChains/Clang.h"
#include "ToolChains/InterfaceStubs.h"
+#include "ToolChains/Flang.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Sanitizers.h"
#include "clang/Config/config.h"
@@ -67,7 +68,8 @@ static ToolChain::RTTIMode CalculateRTTIMode(const ArgList &Args,
}
// -frtti is default, except for the PS4 CPU.
- return (Triple.isPS4CPU()) ? ToolChain::RM_Disabled : ToolChain::RM_Enabled;
+ return (Triple.isPS4CPU() || Triple.isNVPTX()) ? ToolChain::RM_Disabled
+ : ToolChain::RM_Enabled;
}
ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
@@ -151,6 +153,7 @@ static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {
{"cpp", "--driver-mode=cpp"},
{"cl", "--driver-mode=cl"},
{"++", "--driver-mode=g++"},
+ {"flang", "--driver-mode=flang"},
};
for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i) {
@@ -254,6 +257,12 @@ Tool *ToolChain::getClang() const {
return Clang.get();
}
+Tool *ToolChain::getFlang() const {
+ if (!Flang)
+ Flang.reset(new tools::Flang(*this));
+ return Flang.get();
+}
+
Tool *ToolChain::buildAssembler() const {
return new tools::ClangAs(*this);
}
@@ -493,6 +502,7 @@ bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) {
}
Tool *ToolChain::SelectTool(const JobAction &JA) const {
+ if (D.IsFlangMode() && getDriver().ShouldUseFlangCompiler(JA)) return getFlang();
if (getDriver().ShouldUseClangCompiler(JA)) return getClang();
Action::ActionClass AC = JA.getKind();
if (AC == Action::AssembleJobClass && useIntegratedAs())
@@ -541,7 +551,15 @@ std::string ToolChain::GetLinkerPath() const {
}
types::ID ToolChain::LookupTypeForExtension(StringRef Ext) const {
- return types::lookupTypeForExtension(Ext);
+ types::ID id = types::lookupTypeForExtension(Ext);
+
+ // Flang always runs the preprocessor and has no notion of "preprocessed
+ // fortran". Here, TY_PP_Fortran is coerced to TY_Fortran to avoid treating
+ // them differently.
+ if (D.IsFlangMode() && id == types::TY_PP_Fortran)
+ id = types::TY_Fortran;
+
+ return id;
}
bool ToolChain::HasNativeLLVMSupport() const {
@@ -620,6 +638,8 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
Triple.setArchName("arm64");
return Triple.getTriple();
}
+ case llvm::Triple::aarch64_32:
+ return getTripleString();
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumb:
@@ -831,7 +851,7 @@ void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs,
/*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs,
ArgStringList &CC1Args,
ArrayRef<StringRef> Paths) {
- for (const auto Path : Paths) {
+ for (const auto &Path : Paths) {
CC1Args.push_back("-internal-isystem");
CC1Args.push_back(DriverArgs.MakeArgString(Path));
}
diff --git a/clang/lib/Driver/ToolChains/AIX.cpp b/clang/lib/Driver/ToolChains/AIX.cpp
new file mode 100644
index 0000000000000..6fbff61f76565
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/AIX.cpp
@@ -0,0 +1,159 @@
+//===--- AIX.cpp - AIX 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 "AIX.h"
+#include "Arch/PPC.h"
+#include "CommonArgs.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Options.h"
+#include "clang/Driver/SanitizerArgs.h"
+#include "llvm/Option/ArgList.h"
+
+using AIX = clang::driver::toolchains::AIX;
+using namespace clang::driver;
+using namespace clang::driver::tools;
+
+using namespace llvm::opt;
+
+void aix::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ const bool IsArch32Bit = getToolChain().getTriple().isArch32Bit();
+ const bool IsArch64Bit = getToolChain().getTriple().isArch64Bit();
+ // Only support 32 and 64 bit.
+ if (!IsArch32Bit && !IsArch64Bit)
+ llvm_unreachable("Unsupported bit width value.");
+
+ // Specify the mode in which the as(1) command operates.
+ if (IsArch32Bit) {
+ CmdArgs.push_back("-a32");
+ } else {
+ // Must be 64-bit, otherwise asserted already.
+ CmdArgs.push_back("-a64");
+ }
+
+ // Accept an undefined symbol as an extern so that an error message is not
+ // displayed. Otherwise, undefined symbols are flagged with error messages.
+ // FIXME: This should be removed when the assembly generation from the
+ // compiler is able to write externs properly.
+ CmdArgs.push_back("-u");
+
+ // Accept any mixture of instructions.
+ // On Power for AIX and Linux, this behaviour matches that of GCC for both the
+ // user-provided assembler source case and the compiler-produced assembler
+ // source case. Yet XL with user-provided assembler source would not add this.
+ CmdArgs.push_back("-many");
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
+
+ // Specify assembler output file.
+ assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ }
+
+ // Specify assembler input file.
+ // The system assembler on AIX takes exactly one input file. The driver is
+ // expected to invoke as(1) separately for each assembler source input file.
+ if (Inputs.size() != 1)
+ llvm_unreachable("Invalid number of input files.");
+ const InputInfo &II = Inputs[0];
+ assert((II.isFilename() || II.isNothing()) && "Invalid input.");
+ if (II.isFilename())
+ CmdArgs.push_back(II.getFilename());
+
+ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+}
+
+void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs, const ArgList &Args,
+ const char *LinkingOutput) const {
+ const AIX &ToolChain = static_cast<const AIX &>(getToolChain());
+ ArgStringList CmdArgs;
+
+ const bool IsArch32Bit = ToolChain.getTriple().isArch32Bit();
+ const bool IsArch64Bit = ToolChain.getTriple().isArch64Bit();
+ // Only support 32 and 64 bit.
+ if (!(IsArch32Bit || IsArch64Bit))
+ llvm_unreachable("Unsupported bit width value.");
+
+ // Force static linking when "-static" is present.
+ if (Args.hasArg(options::OPT_static))
+ CmdArgs.push_back("-bnso");
+
+ // Specify linker output file.
+ assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ }
+
+ // Set linking mode (i.e., 32/64-bit) and the address of
+ // text and data sections based on arch bit width.
+ if (IsArch32Bit) {
+ CmdArgs.push_back("-b32");
+ CmdArgs.push_back("-bpT:0x10000000");
+ CmdArgs.push_back("-bpD:0x20000000");
+ } else {
+ // Must be 64-bit, otherwise asserted already.
+ CmdArgs.push_back("-b64");
+ CmdArgs.push_back("-bpT:0x100000000");
+ CmdArgs.push_back("-bpD:0x110000000");
+ }
+
+ auto getCrt0Basename = [&Args, IsArch32Bit] {
+ // Enable gprofiling when "-pg" is specified.
+ if (Args.hasArg(options::OPT_pg))
+ return IsArch32Bit ? "gcrt0.o" : "gcrt0_64.o";
+ // Enable profiling when "-p" is specified.
+ else if (Args.hasArg(options::OPT_p))
+ return IsArch32Bit ? "mcrt0.o" : "mcrt0_64.o";
+ else
+ return IsArch32Bit ? "crt0.o" : "crt0_64.o";
+ };
+
+ if (!Args.hasArg(options::OPT_nostdlib)) {
+ CmdArgs.push_back(
+ Args.MakeArgString(ToolChain.GetFilePath(getCrt0Basename())));
+ }
+
+ // Specify linker input file(s).
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
+
+ // Add directory to library search path.
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ ToolChain.AddFilePathLibArgs(Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ // Support POSIX threads if "-pthreads" or "-pthread" is present.
+ if (Args.hasArg(options::OPT_pthreads, options::OPT_pthread))
+ CmdArgs.push_back("-lpthreads");
+
+ CmdArgs.push_back("-lc");
+ }
+
+ const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
+ C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+}
+
+/// AIX - AIX tool chain which can call as(1) and ld(1) directly.
+AIX::AIX(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+ : ToolChain(D, Triple, Args) {
+ getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
+}
+
+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
new file mode 100644
index 0000000000000..69b948bc0ea82
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/AIX.h
@@ -0,0 +1,75 @@
+//===--- AIX.h - AIX 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_AIX_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_AIX_H
+
+#include "clang/Driver/Tool.h"
+#include "clang/Driver/ToolChain.h"
+
+namespace clang {
+namespace driver {
+namespace tools {
+
+/// aix -- Directly call system default assembler and linker.
+namespace aix {
+
+class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
+public:
+ Assembler(const ToolChain &TC) : Tool("aix::Assembler", "assembler", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+public:
+ Linker(const ToolChain &TC) : Tool("aix::Linker", "linker", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
+} // end namespace aix
+
+} // end namespace tools
+} // end namespace driver
+} // end namespace clang
+
+namespace clang {
+namespace driver {
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY AIX : public ToolChain {
+public:
+ AIX(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ bool isPICDefault() const override { return true; }
+ bool isPIEDefault() const override { return false; }
+ bool isPICDefaultForced() const override { return true; }
+
+protected:
+ Tool *buildAssembler() const override;
+ Tool *buildLinker() const override;
+};
+
+} // end namespace toolchains
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_AIX_H
diff --git a/clang/lib/Driver/ToolChains/AMDGPU.h b/clang/lib/Driver/ToolChains/AMDGPU.h
index 5585cc5348615..f4c78bea5cc97 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.h
+++ b/clang/lib/Driver/ToolChains/AMDGPU.h
@@ -55,7 +55,7 @@ protected:
public:
AMDGPUToolChain(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
- unsigned GetDefaultDwarfVersion() const override { return 5; }
+ unsigned GetDefaultDwarfVersion() const override { return 4; }
bool IsIntegratedAssemblerDefault() const override { return true; }
bool IsMathErrnoDefault() const override { return false; }
diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
index 3a5fe6ddeaed5..9c27504dccf5b 100644
--- a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
@@ -43,10 +43,11 @@ std::string aarch64::getAArch64TargetCPU(const ArgList &Args,
else if (CPU.size())
return CPU;
- // Make sure we pick "cyclone" if -arch is used or when targetting a Darwin
- // OS.
+ // Make sure we pick the appropriate Apple CPU if -arch is used or when
+ // targetting a Darwin OS.
if (Args.getLastArg(options::OPT_arch) || Triple.isOSDarwin())
- return "cyclone";
+ return Triple.getArch() == llvm::Triple::aarch64_32 ? "apple-s4"
+ : "apple-a7";
return "generic";
}
@@ -139,7 +140,7 @@ getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,
// Handle CPU name is 'native'.
if (MtuneLowerCase == "native")
MtuneLowerCase = llvm::sys::getHostCPUName();
- if (MtuneLowerCase == "cyclone") {
+ if (MtuneLowerCase == "cyclone" || MtuneLowerCase.find("apple") == 0) {
Features.push_back("+zcm");
Features.push_back("+zcz");
}
diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
index 68a57310ad402..a1923e731489e 100644
--- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -63,12 +63,13 @@ static void getARMHWDivFeatures(const Driver &D, const Arg *A,
}
// Handle -mfpu=.
-static void getARMFPUFeatures(const Driver &D, const Arg *A,
- const ArgList &Args, StringRef FPU,
- std::vector<StringRef> &Features) {
+static unsigned getARMFPUFeatures(const Driver &D, const Arg *A,
+ const ArgList &Args, StringRef FPU,
+ std::vector<StringRef> &Features) {
unsigned FPUID = llvm::ARM::parseFPU(FPU);
if (!llvm::ARM::getFPUFeatures(FPUID, Features))
D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ return FPUID;
}
// Decode ARM features from string like +[no]featureA+[no]featureB+...
@@ -388,18 +389,20 @@ void arm::getARMTargetFeatures(const ToolChain &TC,
checkARMCPUName(D, CPUArg, Args, CPUName, ArchName,
ExtensionFeatures, Triple);
// Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=.
+ unsigned FPUID = llvm::ARM::FK_INVALID;
const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ);
if (WaFPU) {
if (FPUArg)
D.Diag(clang::diag::warn_drv_unused_argument)
<< FPUArg->getAsString(Args);
- getARMFPUFeatures(D, WaFPU, Args, StringRef(WaFPU->getValue()).substr(6),
- Features);
+ (void)getARMFPUFeatures(D, WaFPU, Args, StringRef(WaFPU->getValue()).substr(6),
+ Features);
} else if (FPUArg) {
- getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features);
+ FPUID = getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features);
} else if (Triple.isAndroid() && getARMSubArchVersionNumber(Triple) >= 7) {
const char *AndroidFPU = "neon";
- if (!llvm::ARM::getFPUFeatures(llvm::ARM::parseFPU(AndroidFPU), Features))
+ FPUID = llvm::ARM::parseFPU(AndroidFPU);
+ if (!llvm::ARM::getFPUFeatures(FPUID, Features))
D.Diag(clang::diag::err_drv_clang_unsupported)
<< std::string("-mfpu=") + AndroidFPU;
}
@@ -454,21 +457,21 @@ fp16_fml_fallthrough:
if (ABI == arm::FloatABI::Soft) {
llvm::ARM::getFPUFeatures(llvm::ARM::FK_NONE, Features);
- // Disable all features relating to hardware FP.
- // FIXME: Disabling fpregs should be enough all by itself, since all
- // the other FP features are dependent on it. However
- // there is currently no easy way to test this in clang, so for
- // now just be explicit and disable all known dependent features
- // as well.
- for (std::string Feature : {
- "vfp2", "vfp2sp",
- "vfp3", "vfp3sp", "vfp3d16", "vfp3d16sp",
- "vfp4", "vfp4sp", "vfp4d16", "vfp4d16sp",
- "fp-armv8", "fp-armv8sp", "fp-armv8d16", "fp-armv8d16sp",
- "fullfp16", "neon", "crypto", "dotprod", "fp16fml",
- "mve", "mve.fp",
- "fp64", "d32", "fpregs"})
- Features.push_back(Args.MakeArgString("-" + Feature));
+ // 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"});
+ } 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.emplace_back("-fpregs");
}
// En/disable crc code generation.
diff --git a/clang/lib/Driver/ToolChains/Arch/PPC.cpp b/clang/lib/Driver/ToolChains/Arch/PPC.cpp
index 3e02e57e0f6c7..f1baadaebf41b 100644
--- a/clang/lib/Driver/ToolChains/Arch/PPC.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/PPC.cpp
@@ -53,10 +53,12 @@ std::string ppc::getPPCTargetCPU(const ArgList &Args) {
.Case("7450", "7450")
.Case("G4+", "g4+")
.Case("750", "750")
+ .Case("8548", "e500")
.Case("970", "970")
.Case("G5", "g5")
.Case("a2", "a2")
.Case("a2q", "a2q")
+ .Case("e500", "e500")
.Case("e500mc", "e500mc")
.Case("e5500", "e5500")
.Case("power3", "pwr3")
@@ -68,6 +70,7 @@ std::string ppc::getPPCTargetCPU(const ArgList &Args) {
.Case("power7", "pwr7")
.Case("power8", "pwr8")
.Case("power9", "pwr9")
+ .Case("future", "future")
.Case("pwr3", "pwr3")
.Case("pwr4", "pwr4")
.Case("pwr5", "pwr5")
@@ -101,6 +104,9 @@ const char *ppc::getPPCAsmModeForCPU(StringRef Name) {
void ppc::getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args,
std::vector<StringRef> &Features) {
+ if (Triple.getSubArch() == llvm::Triple::PPCSubArch_spe)
+ Features.push_back("+spe");
+
handleTargetFeaturesGroup(Args, Features, options::OPT_m_ppc_Features_Group);
ppc::FloatABI FloatABI = ppc::getPPCFloatABI(D, Args);
diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
index 624788a5874e3..8c343b8693f32 100644
--- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -357,16 +357,75 @@ static bool getArchFeatures(const Driver &D, StringRef MArch,
void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args,
std::vector<StringRef> &Features) {
- llvm::Optional<StringRef> MArch;
- if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
- MArch = A->getValue();
- else if (Triple.getOS() == llvm::Triple::Linux)
- // RISC-V Linux defaults to rv{32,64}gc.
- MArch = Triple.getArch() == llvm::Triple::riscv32 ? "rv32gc" : "rv64gc";
+ StringRef MArch = getRISCVArch(Args, Triple);
- if (MArch.hasValue() && !getArchFeatures(D, *MArch, Features, Args))
+ if (!getArchFeatures(D, MArch, Features, Args))
return;
+ // Handle features corresponding to "-ffixed-X" options
+ if (Args.hasArg(options::OPT_ffixed_x1))
+ Features.push_back("+reserve-x1");
+ if (Args.hasArg(options::OPT_ffixed_x2))
+ Features.push_back("+reserve-x2");
+ if (Args.hasArg(options::OPT_ffixed_x3))
+ Features.push_back("+reserve-x3");
+ if (Args.hasArg(options::OPT_ffixed_x4))
+ Features.push_back("+reserve-x4");
+ if (Args.hasArg(options::OPT_ffixed_x5))
+ Features.push_back("+reserve-x5");
+ if (Args.hasArg(options::OPT_ffixed_x6))
+ Features.push_back("+reserve-x6");
+ if (Args.hasArg(options::OPT_ffixed_x7))
+ Features.push_back("+reserve-x7");
+ if (Args.hasArg(options::OPT_ffixed_x8))
+ Features.push_back("+reserve-x8");
+ if (Args.hasArg(options::OPT_ffixed_x9))
+ Features.push_back("+reserve-x9");
+ if (Args.hasArg(options::OPT_ffixed_x10))
+ Features.push_back("+reserve-x10");
+ if (Args.hasArg(options::OPT_ffixed_x11))
+ Features.push_back("+reserve-x11");
+ if (Args.hasArg(options::OPT_ffixed_x12))
+ Features.push_back("+reserve-x12");
+ if (Args.hasArg(options::OPT_ffixed_x13))
+ Features.push_back("+reserve-x13");
+ if (Args.hasArg(options::OPT_ffixed_x14))
+ Features.push_back("+reserve-x14");
+ if (Args.hasArg(options::OPT_ffixed_x15))
+ Features.push_back("+reserve-x15");
+ if (Args.hasArg(options::OPT_ffixed_x16))
+ Features.push_back("+reserve-x16");
+ if (Args.hasArg(options::OPT_ffixed_x17))
+ Features.push_back("+reserve-x17");
+ if (Args.hasArg(options::OPT_ffixed_x18))
+ Features.push_back("+reserve-x18");
+ if (Args.hasArg(options::OPT_ffixed_x19))
+ Features.push_back("+reserve-x19");
+ if (Args.hasArg(options::OPT_ffixed_x20))
+ Features.push_back("+reserve-x20");
+ if (Args.hasArg(options::OPT_ffixed_x21))
+ Features.push_back("+reserve-x21");
+ if (Args.hasArg(options::OPT_ffixed_x22))
+ Features.push_back("+reserve-x22");
+ if (Args.hasArg(options::OPT_ffixed_x23))
+ Features.push_back("+reserve-x23");
+ if (Args.hasArg(options::OPT_ffixed_x24))
+ Features.push_back("+reserve-x24");
+ if (Args.hasArg(options::OPT_ffixed_x25))
+ Features.push_back("+reserve-x25");
+ if (Args.hasArg(options::OPT_ffixed_x26))
+ Features.push_back("+reserve-x26");
+ if (Args.hasArg(options::OPT_ffixed_x27))
+ Features.push_back("+reserve-x27");
+ if (Args.hasArg(options::OPT_ffixed_x28))
+ Features.push_back("+reserve-x28");
+ if (Args.hasArg(options::OPT_ffixed_x29))
+ Features.push_back("+reserve-x29");
+ if (Args.hasArg(options::OPT_ffixed_x30))
+ Features.push_back("+reserve-x30");
+ if (Args.hasArg(options::OPT_ffixed_x31))
+ Features.push_back("+reserve-x31");
+
// -mrelax is default, unless -mno-relax is specified.
if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true))
Features.push_back("+relax");
@@ -391,12 +450,132 @@ StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) {
Triple.getArch() == llvm::Triple::riscv64) &&
"Unexpected triple");
+ // GCC's logic around choosing a default `-mabi=` is complex. If GCC is not
+ // configured using `--with-abi=`, then the logic for the default choice is
+ // defined in config.gcc. This function is based on the logic in GCC 9.2.0. We
+ // deviate from GCC's default only on baremetal targets (UnknownOS) where
+ // neither `-march` nor `-mabi` is specified.
+ //
+ // The logic uses the following, in order:
+ // 1. Explicit choices using `--with-abi=`
+ // 2. A default based on `--with-arch=`, if provided
+ // 3. A default based on the target triple's arch
+ //
+ // The logic in config.gcc is a little circular but it is not inconsistent.
+ //
+ // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
+ // and `-mabi=` respectively instead.
+
+ // 1. If `-mabi=` is specified, use it.
if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
return A->getValue();
- // RISC-V Linux defaults to ilp32d/lp64d
- if (Triple.getOS() == llvm::Triple::Linux)
- return Triple.getArch() == llvm::Triple::riscv32 ? "ilp32d" : "lp64d";
- else
- return Triple.getArch() == llvm::Triple::riscv32 ? "ilp32" : "lp64";
+ // 2. Choose a default based on `-march=`
+ //
+ // rv32g | rv32*d -> ilp32d
+ // rv32e -> ilp32e
+ // rv32* -> ilp32
+ // rv64g | rv64*d -> lp64d
+ // rv64* -> lp64
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ StringRef MArch = A->getValue();
+
+ if (MArch.startswith_lower("rv32")) {
+ // FIXME: parse `March` to find `D` extension properly
+ if (MArch.substr(4).contains_lower("d") ||
+ MArch.startswith_lower("rv32g"))
+ return "ilp32d";
+ else if (MArch.startswith_lower("rv32e"))
+ return "ilp32e";
+ else
+ return "ilp32";
+ } else if (MArch.startswith_lower("rv64")) {
+ // FIXME: parse `March` to find `D` extension properly
+ if (MArch.substr(4).contains_lower("d") ||
+ MArch.startswith_lower("rv64g"))
+ return "lp64d";
+ else
+ return "lp64";
+ }
+ }
+
+ // 3. Choose a default based on the triple
+ //
+ // We deviate from GCC's defaults here:
+ // - On `riscv{XLEN}-unknown-elf` we use the integer calling convention only.
+ // - On all other OSs we use the double floating point calling convention.
+ if (Triple.getArch() == llvm::Triple::riscv32) {
+ if (Triple.getOS() == llvm::Triple::UnknownOS)
+ return "ilp32";
+ else
+ return "ilp32d";
+ } else {
+ if (Triple.getOS() == llvm::Triple::UnknownOS)
+ return "lp64";
+ else
+ return "lp64d";
+ }
+}
+
+StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple) {
+ assert((Triple.getArch() == llvm::Triple::riscv32 ||
+ Triple.getArch() == llvm::Triple::riscv64) &&
+ "Unexpected triple");
+
+ // GCC's logic around choosing a default `-march=` is complex. If GCC is not
+ // configured using `--with-arch=`, then the logic for the default choice is
+ // defined in config.gcc. This function is based on the logic in GCC 9.2.0. We
+ // deviate from GCC's default only on baremetal targets (UnknownOS) where
+ // neither `-march` nor `-mabi` is specified.
+ //
+ // The logic uses the following, in order:
+ // 1. Explicit choices using `--with-arch=`
+ // 2. A default based on `--with-abi=`, if provided
+ // 3. A default based on the target triple's arch
+ //
+ // The logic in config.gcc is a little circular but it is not inconsistent.
+ //
+ // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
+ // and `-mabi=` respectively instead.
+ //
+ // Clang does not yet support MULTILIB_REUSE, so we use `rv{XLEN}imafdc`
+ // instead of `rv{XLEN}gc` though they are (currently) equivalent.
+
+ // 1. If `-march=` is specified, use it.
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
+ return A->getValue();
+
+ // 2. Choose a default based on `-mabi=`
+ //
+ // ilp32e -> rv32e
+ // ilp32 | ilp32f | ilp32d -> rv32imafdc
+ // lp64 | lp64f | lp64d -> rv64imafdc
+ if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
+ StringRef MABI = A->getValue();
+
+ if (MABI.equals_lower("ilp32e"))
+ return "rv32e";
+ else if (MABI.startswith_lower("ilp32"))
+ return "rv32imafdc";
+ else if (MABI.startswith_lower("lp64"))
+ return "rv64imafdc";
+ }
+
+ // 3. Choose a default based on the triple
+ //
+ // We deviate from GCC's defaults here:
+ // - On `riscv{XLEN}-unknown-elf` we default to `rv{XLEN}imac`
+ // - On all other OSs we use `rv{XLEN}imafdc` (equivalent to `rv{XLEN}gc`)
+ if (Triple.getArch() == llvm::Triple::riscv32) {
+ if (Triple.getOS() == llvm::Triple::UnknownOS)
+ return "rv32imac";
+ else
+ return "rv32imafdc";
+ } else {
+ if (Triple.getOS() == llvm::Triple::UnknownOS)
+ return "rv64imac";
+ else
+ return "rv64imafdc";
+ }
}
diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.h b/clang/lib/Driver/ToolChains/Arch/RISCV.h
index 10eaf3c897b68..d4a519cdab340 100644
--- a/clang/lib/Driver/ToolChains/Arch/RISCV.h
+++ b/clang/lib/Driver/ToolChains/Arch/RISCV.h
@@ -24,6 +24,8 @@ void getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
std::vector<llvm::StringRef> &Features);
StringRef getRISCVABI(const llvm::opt::ArgList &Args,
const llvm::Triple &Triple);
+StringRef getRISCVArch(const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple);
} // end namespace riscv
} // namespace tools
} // end namespace driver
diff --git a/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp b/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp
index ca60b85cf8a05..2b77d59fdc66b 100644
--- a/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp
@@ -9,15 +9,27 @@
#include "SystemZ.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Support/Host.h"
using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;
-const char *systemz::getSystemZTargetCPU(const ArgList &Args) {
- if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ))
- return A->getValue();
+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();
+ if (!CPU.empty() && CPU != "generic")
+ return CPU;
+ else
+ return "";
+ }
+
+ return CPUName;
+ }
return "z10";
}
diff --git a/clang/lib/Driver/ToolChains/Arch/SystemZ.h b/clang/lib/Driver/ToolChains/Arch/SystemZ.h
index 11d77fa01cc88..77dcbc47be5c0 100644
--- a/clang/lib/Driver/ToolChains/Arch/SystemZ.h
+++ b/clang/lib/Driver/ToolChains/Arch/SystemZ.h
@@ -11,6 +11,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Option/Option.h"
+#include <string>
#include <vector>
namespace clang {
@@ -18,7 +19,7 @@ namespace driver {
namespace tools {
namespace systemz {
-const char *getSystemZTargetCPU(const llvm::opt::ArgList &Args);
+std::string getSystemZTargetCPU(const llvm::opt::ArgList &Args);
void getSystemZTargetFeatures(const llvm::opt::ArgList &Args,
std::vector<llvm::StringRef> &Features);
diff --git a/clang/lib/Driver/ToolChains/Arch/X86.cpp b/clang/lib/Driver/ToolChains/Arch/X86.cpp
index d2b97bf6ad719..d1e0c8253b799 100644
--- a/clang/lib/Driver/ToolChains/Arch/X86.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/X86.cpp
@@ -63,8 +63,7 @@ const char *x86::getX86TargetCPU(const ArgList &Args,
// Select the default CPU if none was given (or detection failed).
- if (Triple.getArch() != llvm::Triple::x86_64 &&
- Triple.getArch() != llvm::Triple::x86)
+ if (!Triple.isX86())
return nullptr; // This routine is only handling x86 targets.
bool Is64Bit = Triple.getArch() == llvm::Triple::x86_64;
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 55d631733add2..9b3055413e9e6 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -302,6 +302,96 @@ static void ParseMPreferVectorWidth(const Driver &D, const ArgList &Args,
}
}
+static void getWebAssemblyTargetFeatures(const ArgList &Args,
+ std::vector<StringRef> &Features) {
+ handleTargetFeaturesGroup(Args, Features, options::OPT_m_wasm_Features_Group);
+}
+
+static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
+ const ArgList &Args, ArgStringList &CmdArgs,
+ bool ForAS) {
+ const Driver &D = TC.getDriver();
+ std::vector<StringRef> Features;
+ switch (Triple.getArch()) {
+ default:
+ break;
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ mips::getMIPSTargetFeatures(D, Triple, Args, Features);
+ break;
+
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ arm::getARMTargetFeatures(TC, Triple, Args, CmdArgs, Features, ForAS);
+ break;
+
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
+ ppc::getPPCTargetFeatures(D, Triple, Args, Features);
+ break;
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ riscv::getRISCVTargetFeatures(D, Triple, Args, Features);
+ break;
+ case llvm::Triple::systemz:
+ systemz::getSystemZTargetFeatures(Args, Features);
+ break;
+ case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_32:
+ case llvm::Triple::aarch64_be:
+ aarch64::getAArch64TargetFeatures(D, Triple, Args, Features);
+ break;
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ x86::getX86TargetFeatures(D, Triple, Args, Features);
+ break;
+ case llvm::Triple::hexagon:
+ hexagon::getHexagonTargetFeatures(D, Args, Features);
+ break;
+ case llvm::Triple::wasm32:
+ case llvm::Triple::wasm64:
+ getWebAssemblyTargetFeatures(Args, Features);
+ break;
+ case llvm::Triple::sparc:
+ case llvm::Triple::sparcel:
+ case llvm::Triple::sparcv9:
+ sparc::getSparcTargetFeatures(D, Args, Features);
+ break;
+ case llvm::Triple::r600:
+ case llvm::Triple::amdgcn:
+ amdgpu::getAMDGPUTargetFeatures(D, Args, Features);
+ break;
+ case llvm::Triple::msp430:
+ msp430::getMSP430TargetFeatures(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());
+ }
+}
+
static bool
shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime,
const llvm::Triple &Triple) {
@@ -378,15 +468,20 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType,
CmdArgs.push_back("-fexceptions");
}
-static bool ShouldDisableAutolink(const ArgList &Args, const ToolChain &TC) {
+static bool ShouldEnableAutolink(const ArgList &Args, const ToolChain &TC,
+ const JobAction &JA) {
bool Default = true;
if (TC.getTriple().isOSDarwin()) {
// The native darwin assembler doesn't support the linker_option directives,
// so we disable them if we think the .s file will be passed to it.
Default = TC.useIntegratedAs();
}
- return !Args.hasFlag(options::OPT_fautolink, options::OPT_fno_autolink,
- Default);
+ // The linker_option directives are intended for host compilation.
+ if (JA.isDeviceOffloading(Action::OFK_Cuda) ||
+ JA.isDeviceOffloading(Action::OFK_HIP))
+ Default = false;
+ return Args.hasFlag(options::OPT_fautolink, options::OPT_fno_autolink,
+ Default);
}
static bool ShouldDisableDwarfDirectory(const ArgList &Args,
@@ -443,6 +538,8 @@ static bool useFramePointerForTargetByDefault(const ArgList &Args,
case llvm::Triple::ppc64le:
case llvm::Triple::riscv32:
case llvm::Triple::riscv64:
+ case llvm::Triple::amdgcn:
+ case llvm::Triple::r600:
return !areOptimizationsEnabled(Args);
default:
break;
@@ -506,9 +603,9 @@ getFramePointerKind(const ArgList &Args, const llvm::Triple &Triple) {
bool OmitFP = A && A->getOption().matches(options::OPT_fomit_frame_pointer);
bool NoOmitFP =
A && A->getOption().matches(options::OPT_fno_omit_frame_pointer);
- bool KeepLeaf =
- Args.hasFlag(options::OPT_momit_leaf_frame_pointer,
- options::OPT_mno_omit_leaf_frame_pointer, Triple.isPS4CPU());
+ bool KeepLeaf = Args.hasFlag(options::OPT_momit_leaf_frame_pointer,
+ options::OPT_mno_omit_leaf_frame_pointer,
+ Triple.isAArch64() || Triple.isPS4CPU());
if (NoOmitFP || mustUseNonLeafFramePointerForTarget(Triple) ||
(!OmitFP && useFramePointerForTargetByDefault(Args, Triple))) {
if (KeepLeaf)
@@ -533,16 +630,33 @@ static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs,
/// Add a CC1 and CC1AS option to specify the debug file path prefix map.
static void addDebugPrefixMapArg(const Driver &D, const ArgList &Args, ArgStringList &CmdArgs) {
- for (const Arg *A : Args.filtered(options::OPT_fdebug_prefix_map_EQ)) {
+ for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ,
+ options::OPT_fdebug_prefix_map_EQ)) {
StringRef Map = A->getValue();
if (Map.find('=') == StringRef::npos)
- D.Diag(diag::err_drv_invalid_argument_to_fdebug_prefix_map) << Map;
+ D.Diag(diag::err_drv_invalid_argument_to_option)
+ << Map << A->getOption().getName();
else
CmdArgs.push_back(Args.MakeArgString("-fdebug-prefix-map=" + Map));
A->claim();
}
}
+/// Add a CC1 and CC1AS option to specify the macro file path prefix map.
+static void addMacroPrefixMapArg(const Driver &D, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ,
+ options::OPT_fmacro_prefix_map_EQ)) {
+ StringRef Map = A->getValue();
+ if (Map.find('=') == StringRef::npos)
+ D.Diag(diag::err_drv_invalid_argument_to_option)
+ << Map << A->getOption().getName();
+ else
+ CmdArgs.push_back(Args.MakeArgString("-fmacro-prefix-map=" + Map));
+ A->claim();
+ }
+}
+
/// Vectorize at all optimization levels greater than 1 except for -Oz.
/// For -Oz the loop vectorizer is disabled, while the slp vectorizer is
/// enabled.
@@ -802,7 +916,9 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C,
if ((Args.hasArg(options::OPT_c) || Args.hasArg(options::OPT_S)) &&
(EmitCovNotes || EmitCovData) && Output.isFilename()) {
SmallString<128> OutputFilename;
- if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o))
+ if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT__SLASH_Fo))
+ OutputFilename = FinalOutput->getValue();
+ else if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o))
OutputFilename = FinalOutput->getValue();
else
OutputFilename = llvm::sys::path::filename(Output.getBaseInput());
@@ -883,6 +999,9 @@ static void RenderDebugEnablingArgs(const ArgList &Args, ArgStringList &CmdArgs,
case codegenoptions::DebugLineTablesOnly:
CmdArgs.push_back("-debug-info-kind=line-tables-only");
break;
+ case codegenoptions::DebugInfoConstructor:
+ CmdArgs.push_back("-debug-info-kind=constructor");
+ break;
case codegenoptions::LimitedDebugInfo:
CmdArgs.push_back("-debug-info-kind=limited");
break;
@@ -1248,6 +1367,8 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
// For IAMCU add special include arguments.
getToolChain().AddIAMCUIncludeArgs(Args, CmdArgs);
}
+
+ addMacroPrefixMapArg(D, Args, CmdArgs);
}
// FIXME: Move to target hook.
@@ -1257,6 +1378,7 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) {
return true;
case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_32:
case llvm::Triple::aarch64_be:
case llvm::Triple::arm:
case llvm::Triple::armeb:
@@ -1296,6 +1418,116 @@ static bool isNoCommonDefault(const llvm::Triple &Triple) {
}
}
+static bool hasMultipleInvocations(const llvm::Triple &Triple,
+ const ArgList &Args) {
+ // Supported only on Darwin where we invoke the compiler multiple times
+ // followed by an invocation to lipo.
+ if (!Triple.isOSDarwin())
+ return false;
+ // If more than one "-arch <arch>" is specified, we're targeting multiple
+ // architectures resulting in a fat binary.
+ return Args.getAllArgValues(options::OPT_arch).size() > 1;
+}
+
+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 = ::hasMultipleInvocations(Triple, Args);
+ 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 &Input,
+ 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("-opt-record-file");
+
+ const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);
+ if (A) {
+ CmdArgs.push_back(A->getValue());
+ } else {
+ bool hasMultipleArchs =
+ Triple.isOSDarwin() && // Only supported on Darwin platforms.
+ Args.getAllArgValues(options::OPT_arch).size() > 1;
+
+ SmallString<128> F;
+
+ if (Args.hasArg(options::OPT_c) || Args.hasArg(options::OPT_S)) {
+ if (Arg *FinalOutput = Args.getLastArg(options::OPT_o))
+ F = FinalOutput->getValue();
+ } else {
+ if (Format != "yaml" && // For YAML, keep the original behavior.
+ Triple.isOSDarwin() && // Enable this only on darwin, since it's the only platform supporting .dSYM bundles.
+ Output.isFilename())
+ F = Output.getFilename();
+ }
+
+ if (F.empty()) {
+ // Use the input filename.
+ F = llvm::sys::path::stem(Input.getBaseInput());
+
+ // If we're compiling for an offload architecture (i.e. a CUDA device),
+ // we need to make the file name for the device compilation different
+ // from the host compilation.
+ if (!JA.isDeviceOffloading(Action::OFK_None) &&
+ !JA.isDeviceOffloading(Action::OFK_Host)) {
+ llvm::sys::path::replace_extension(F, "");
+ F += Action::GetOffloadingFileNamePrefix(JA.getOffloadingDeviceKind(),
+ Triple.normalize());
+ F += "-";
+ F += JA.getOffloadingArch();
+ }
+ }
+
+ // If we're having more than one "-arch", we should name the files
+ // differently so that every cc1 invocation writes to a different file.
+ // We're doing that by appending "-<arch>" with "<arch>" being the arch
+ // name from the triple.
+ if (hasMultipleArchs) {
+ // First, remember the extension.
+ SmallString<64> OldExtension = llvm::sys::path::extension(F);
+ // then, remove it.
+ llvm::sys::path::replace_extension(F, "");
+ // attach -<arch> to it.
+ F += "-";
+ F += Triple.getArchName();
+ // put back the extension.
+ llvm::sys::path::replace_extension(F, OldExtension);
+ }
+
+ SmallString<32> Extension;
+ Extension += "opt.";
+ Extension += Format;
+
+ llvm::sys::path::replace_extension(F, Extension);
+ CmdArgs.push_back(Args.MakeArgString(F));
+ }
+
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) {
+ CmdArgs.push_back("-opt-record-passes");
+ CmdArgs.push_back(A->getValue());
+ }
+
+ if (!Format.empty()) {
+ CmdArgs.push_back("-opt-record-format");
+ CmdArgs.push_back(Format.data());
+ }
+}
+
namespace {
void RenderARMABI(const llvm::Triple &Triple, const ArgList &Args,
ArgStringList &CmdArgs) {
@@ -1379,6 +1611,7 @@ void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple,
break;
case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_32:
case llvm::Triple::aarch64_be:
AddAArch64TargetArgs(Args, CmdArgs);
CmdArgs.push_back("-fallow-half-arguments-and-returns");
@@ -1432,56 +1665,6 @@ void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple,
}
}
-// Parse -mbranch-protection=<protection>[+<protection>]* where
-// <protection> ::= standard | none | [bti,pac-ret[+b-key,+leaf]*]
-// Returns a triple of (return address signing Scope, signing key, require
-// landing pads)
-static std::tuple<StringRef, StringRef, bool>
-ParseAArch64BranchProtection(const Driver &D, const ArgList &Args,
- const Arg *A) {
- StringRef Scope = "none";
- StringRef Key = "a_key";
- bool IndirectBranches = false;
-
- StringRef Value = A->getValue();
- // This maps onto -mbranch-protection=<scope>+<key>
-
- if (Value.equals("standard")) {
- Scope = "non-leaf";
- Key = "a_key";
- IndirectBranches = true;
-
- } else if (!Value.equals("none")) {
- SmallVector<StringRef, 4> BranchProtection;
- StringRef(A->getValue()).split(BranchProtection, '+');
-
- auto Protection = BranchProtection.begin();
- while (Protection != BranchProtection.end()) {
- if (Protection->equals("bti"))
- IndirectBranches = true;
- else if (Protection->equals("pac-ret")) {
- Scope = "non-leaf";
- while (++Protection != BranchProtection.end()) {
- // Inner loop as "leaf" and "b-key" options must only appear attached
- // to pac-ret.
- if (Protection->equals("leaf"))
- Scope = "all";
- else if (Protection->equals("b-key"))
- Key = "b_key";
- else
- break;
- }
- Protection--;
- } else
- D.Diag(diag::err_invalid_branch_protection)
- << *Protection << A->getAsString(Args);
- Protection++;
- }
- }
-
- return std::make_tuple(Scope, Key, IndirectBranches);
-}
-
namespace {
void RenderAArch64ABI(const llvm::Triple &Triple, const ArgList &Args,
ArgStringList &CmdArgs) {
@@ -1553,9 +1736,16 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
<< Scope << A->getAsString(Args);
Key = "a_key";
IndirectBranches = false;
- } else
- std::tie(Scope, Key, IndirectBranches) =
- ParseAArch64BranchProtection(D, Args, A);
+ } else {
+ StringRef Err;
+ llvm::AArch64::ParsedBranchProtection PBP;
+ if (!llvm::AArch64::parseBranchProtection(A->getValue(), PBP, Err))
+ D.Diag(diag::err_invalid_branch_protection)
+ << Err << A->getAsString(Args);
+ Scope = PBP.Scope;
+ Key = PBP.Key;
+ IndirectBranches = PBP.BranchTargetEnforcement;
+ }
CmdArgs.push_back(
Args.MakeArgString(Twine("-msign-return-address=") + Scope));
@@ -1713,7 +1903,8 @@ void Clang::AddPPCTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
// Select the ABI to use.
const char *ABIName = nullptr;
- if (getToolChain().getTriple().isOSLinux())
+ const llvm::Triple &T = getToolChain().getTriple();
+ if (T.isOSBinFormatELF()) {
switch (getToolChain().getArch()) {
case llvm::Triple::ppc64: {
// When targeting a processor that supports QPX, or if QPX is
@@ -1728,7 +1919,10 @@ void Clang::AddPPCTargetArgs(const ArgList &Args,
break;
}
- ABIName = "elfv1";
+ if (T.isMusl() || (T.isOSFreeBSD() && T.getOSMajorVersion() >= 13))
+ ABIName = "elfv2";
+ else
+ ABIName = "elfv1";
break;
}
case llvm::Triple::ppc64le:
@@ -1737,6 +1931,7 @@ void Clang::AddPPCTargetArgs(const ArgList &Args,
default:
break;
}
+ }
bool IEEELongDouble = false;
for (const Arg *A : Args.filtered(options::OPT_mabi_EQ)) {
@@ -1804,12 +1999,75 @@ void Clang::AddSparcTargetArgs(const ArgList &Args,
void Clang::AddSystemZTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
- if (Args.hasFlag(options::OPT_mbackchain, options::OPT_mno_backchain, false))
+ bool HasBackchain = Args.hasFlag(options::OPT_mbackchain,
+ options::OPT_mno_backchain, false);
+ bool HasPackedStack = Args.hasFlag(options::OPT_mpacked_stack,
+ options::OPT_mno_packed_stack, false);
+ if (HasBackchain && HasPackedStack) {
+ 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);
+ }
+ 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)));
+ }
+ }
}
void Clang::AddX86TargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
+ const Driver &D = getToolChain().getDriver();
+ addX86AlignBranchArgs(D, Args, CmdArgs);
+
if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) ||
Args.hasArg(options::OPT_mkernel) ||
Args.hasArg(options::OPT_fapple_kext))
@@ -1839,10 +2097,10 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
CmdArgs.push_back("-mllvm");
CmdArgs.push_back(Args.MakeArgString("-x86-asm-syntax=" + Value));
} else {
- getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)
+ D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Value;
}
- } else if (getToolChain().getDriver().IsCLMode()) {
+ } else if (D.IsCLMode()) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-x86-asm-syntax=intel");
}
@@ -2193,6 +2451,12 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
} else if (Value == "-fdebug-compilation-dir") {
CmdArgs.push_back("-fdebug-compilation-dir");
TakeNextArg = true;
+ } else if (Value.consume_front("-fdebug-compilation-dir=")) {
+ // The flag is a -Wa / -Xassembler argument and Options doesn't
+ // parse the argument, so this isn't automatically aliased to
+ // -fdebug-compilation-dir (without '=') here.
+ CmdArgs.push_back("-fdebug-compilation-dir");
+ CmdArgs.push_back(Value.data());
} else {
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Value;
@@ -2229,9 +2493,18 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
bool AssociativeMath = false;
bool ReciprocalMath = false;
bool SignedZeros = true;
- bool TrappingMath = true;
+ bool TrappingMath = false; // Implemented via -ffp-exception-behavior
+ bool TrappingMathPresent = false; // Is trapping-math in args, and not
+ // overriden by ffp-exception-behavior?
+ bool RoundingFPMath = false;
+ bool RoundingMathPresent = false; // Is rounding-math in args?
+ // -ffp-model values: strict, fast, precise
+ StringRef FPModel = "";
+ // -ffp-exception-behavior options: strict, maytrap, ignore
+ StringRef FPExceptionBehavior = "";
StringRef DenormalFPMath = "";
StringRef FPContract = "";
+ bool StrictFPModel = false;
if (const Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
CmdArgs.push_back("-mlimit-float-precision");
@@ -2239,7 +2512,65 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
}
for (const Arg *A : Args) {
- switch (A->getOption().getID()) {
+ auto optID = A->getOption().getID();
+ bool PreciseFPModel = false;
+ switch (optID) {
+ default:
+ break;
+ case options::OPT_ffp_model_EQ: {
+ // If -ffp-model= is seen, reset to fno-fast-math
+ HonorINFs = true;
+ HonorNaNs = true;
+ // Turning *off* -ffast-math restores the toolchain default.
+ MathErrno = TC.IsMathErrnoDefault();
+ AssociativeMath = false;
+ ReciprocalMath = false;
+ SignedZeros = true;
+ // -fno_fast_math restores default denormal and fpcontract handling
+ DenormalFPMath = "";
+ FPContract = "";
+ StringRef Val = A->getValue();
+ if (OFastEnabled && !Val.equals("fast")) {
+ // Only -ffp-model=fast is compatible with OFast, ignore.
+ D.Diag(clang::diag::warn_drv_overriding_flag_option)
+ << Args.MakeArgString("-ffp-model=" + Val)
+ << "-Ofast";
+ break;
+ }
+ StrictFPModel = false;
+ PreciseFPModel = true;
+ // ffp-model= is a Driver option, it is entirely rewritten into more
+ // granular options before being passed into cc1.
+ // Use the gcc option in the switch below.
+ if (!FPModel.empty() && !FPModel.equals(Val)) {
+ D.Diag(clang::diag::warn_drv_overriding_flag_option)
+ << Args.MakeArgString("-ffp-model=" + FPModel)
+ << Args.MakeArgString("-ffp-model=" + Val);
+ FPContract = "";
+ }
+ if (Val.equals("fast")) {
+ optID = options::OPT_ffast_math;
+ FPModel = Val;
+ FPContract = "fast";
+ } else if (Val.equals("precise")) {
+ optID = options::OPT_ffp_contract;
+ FPModel = Val;
+ FPContract = "fast";
+ PreciseFPModel = true;
+ } else if (Val.equals("strict")) {
+ StrictFPModel = true;
+ optID = options::OPT_frounding_math;
+ FPExceptionBehavior = "strict";
+ FPModel = Val;
+ TrappingMath = true;
+ } else
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Val;
+ break;
+ }
+ }
+
+ switch (optID) {
// If this isn't an FP option skip the claim below
default: continue;
@@ -2256,20 +2587,83 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
case options::OPT_fno_reciprocal_math: ReciprocalMath = false; break;
case options::OPT_fsigned_zeros: SignedZeros = true; break;
case options::OPT_fno_signed_zeros: SignedZeros = false; break;
- case options::OPT_ftrapping_math: TrappingMath = true; break;
- case options::OPT_fno_trapping_math: TrappingMath = false; break;
+ case options::OPT_ftrapping_math:
+ if (!TrappingMathPresent && !FPExceptionBehavior.empty() &&
+ !FPExceptionBehavior.equals("strict"))
+ // Warn that previous value of option is overridden.
+ D.Diag(clang::diag::warn_drv_overriding_flag_option)
+ << Args.MakeArgString("-ffp-exception-behavior=" + FPExceptionBehavior)
+ << "-ftrapping-math";
+ TrappingMath = true;
+ TrappingMathPresent = true;
+ FPExceptionBehavior = "strict";
+ break;
+ case options::OPT_fno_trapping_math:
+ if (!TrappingMathPresent && !FPExceptionBehavior.empty() &&
+ !FPExceptionBehavior.equals("ignore"))
+ // Warn that previous value of option is overridden.
+ D.Diag(clang::diag::warn_drv_overriding_flag_option)
+ << Args.MakeArgString("-ffp-exception-behavior=" + FPExceptionBehavior)
+ << "-fno-trapping-math";
+ TrappingMath = false;
+ TrappingMathPresent = true;
+ FPExceptionBehavior = "ignore";
+ break;
+
+ case options::OPT_frounding_math:
+ RoundingFPMath = true;
+ RoundingMathPresent = true;
+ break;
+
+ case options::OPT_fno_rounding_math:
+ RoundingFPMath = false;
+ RoundingMathPresent = false;
+ break;
case options::OPT_fdenormal_fp_math_EQ:
DenormalFPMath = A->getValue();
break;
- // Validate and pass through -fp-contract option.
+ // Validate and pass through -ffp-contract option.
case options::OPT_ffp_contract: {
StringRef Val = A->getValue();
- if (Val == "fast" || Val == "on" || Val == "off")
+ if (PreciseFPModel) {
+ // -ffp-model=precise enables ffp-contract=fast as a side effect
+ // the FPContract value has already been set to a string literal
+ // and the Val string isn't a pertinent value.
+ ;
+ } else if (Val.equals("fast") || Val.equals("on") || Val.equals("off"))
FPContract = Val;
else
D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Val;
+ break;
+ }
+
+ // Validate and pass through -ffp-model option.
+ case options::OPT_ffp_model_EQ:
+ // This should only occur in the error case
+ // since the optID has been replaced by a more granular
+ // floating point option.
+ break;
+
+ // Validate and pass through -ffp-exception-behavior option.
+ case options::OPT_ffp_exception_behavior_EQ: {
+ StringRef Val = A->getValue();
+ if (!TrappingMathPresent && !FPExceptionBehavior.empty() &&
+ !FPExceptionBehavior.equals(Val))
+ // Warn that previous value of option is overridden.
+ D.Diag(clang::diag::warn_drv_overriding_flag_option)
+ << Args.MakeArgString("-ffp-exception-behavior=" + FPExceptionBehavior)
+ << Args.MakeArgString("-ffp-exception-behavior=" + Val);
+ TrappingMath = TrappingMathPresent = false;
+ if (Val.equals("ignore") || Val.equals("maytrap"))
+ FPExceptionBehavior = Val;
+ else if (Val.equals("strict")) {
+ FPExceptionBehavior = Val;
+ TrappingMath = TrappingMathPresent = true;
+ } else
+ D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Val;
break;
}
@@ -2288,12 +2682,14 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
ReciprocalMath = true;
SignedZeros = false;
TrappingMath = false;
+ FPExceptionBehavior = "";
break;
case options::OPT_fno_unsafe_math_optimizations:
AssociativeMath = false;
ReciprocalMath = false;
SignedZeros = true;
TrappingMath = true;
+ FPExceptionBehavior = "strict";
// -fno_unsafe_math_optimizations restores default denormal handling
DenormalFPMath = "";
break;
@@ -2311,6 +2707,7 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
ReciprocalMath = true;
SignedZeros = false;
TrappingMath = false;
+ RoundingFPMath = false;
// If fast-math is set then set the fp-contract mode to fast.
FPContract = "fast";
break;
@@ -2324,12 +2721,31 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
AssociativeMath = false;
ReciprocalMath = false;
SignedZeros = true;
- TrappingMath = true;
+ TrappingMath = false;
+ RoundingFPMath = false;
// -fno_fast_math restores default denormal and fpcontract handling
DenormalFPMath = "";
FPContract = "";
break;
}
+ if (StrictFPModel) {
+ // If -ffp-model=strict has been specified on command line but
+ // subsequent options conflict then emit warning diagnostic.
+ if (HonorINFs && HonorNaNs &&
+ !AssociativeMath && !ReciprocalMath &&
+ SignedZeros && TrappingMath && RoundingFPMath &&
+ DenormalFPMath.empty() && FPContract.empty())
+ // OK: Current Arg doesn't conflict with -ffp-model=strict
+ ;
+ else {
+ StrictFPModel = false;
+ FPModel = "";
+ D.Diag(clang::diag::warn_drv_overriding_flag_option)
+ << "-ffp-model=strict" <<
+ ((A->getNumValues() == 0) ? A->getSpelling()
+ : Args.MakeArgString(A->getSpelling() + A->getValue()));
+ }
+ }
// If we handled this option claim it
A->claim();
@@ -2357,7 +2773,11 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
if (ReciprocalMath)
CmdArgs.push_back("-freciprocal-math");
- if (!TrappingMath)
+ if (TrappingMath) {
+ // FP Exception Behavior is also set to strict
+ assert(FPExceptionBehavior.equals("strict"));
+ CmdArgs.push_back("-ftrapping-math");
+ } else if (TrappingMathPresent)
CmdArgs.push_back("-fno-trapping-math");
if (!DenormalFPMath.empty())
@@ -2367,14 +2787,37 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
if (!FPContract.empty())
CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + FPContract));
+ if (!RoundingFPMath)
+ CmdArgs.push_back(Args.MakeArgString("-fno-rounding-math"));
+
+ if (RoundingFPMath && RoundingMathPresent)
+ CmdArgs.push_back(Args.MakeArgString("-frounding-math"));
+
+ if (!FPExceptionBehavior.empty())
+ CmdArgs.push_back(Args.MakeArgString("-ffp-exception-behavior=" +
+ FPExceptionBehavior));
+
ParseMRecip(D, Args, CmdArgs);
// -ffast-math enables the __FAST_MATH__ preprocessor macro, but check for the
// individual features enabled by -ffast-math instead of the option itself as
// that's consistent with gcc's behaviour.
if (!HonorINFs && !HonorNaNs && !MathErrno && AssociativeMath &&
- ReciprocalMath && !SignedZeros && !TrappingMath)
+ ReciprocalMath && !SignedZeros && !TrappingMath && !RoundingFPMath) {
CmdArgs.push_back("-ffast-math");
+ if (FPModel.equals("fast")) {
+ if (FPContract.equals("fast"))
+ // All set, do nothing.
+ ;
+ else if (FPContract.empty())
+ // Enable -ffp-contract=fast
+ CmdArgs.push_back(Args.MakeArgString("-ffp-contract=fast"));
+ else
+ D.Diag(clang::diag::warn_drv_overriding_flag_option)
+ << "-ffp-model=fast"
+ << Args.MakeArgString("-ffp-contract=" + FPContract);
+ }
+ }
// Handle __FINITE_MATH_ONLY__ similarly.
if (!HonorINFs && !HonorNaNs)
@@ -2423,8 +2866,13 @@ static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs,
CmdArgs.push_back("-analyzer-disable-checker=unix.Vfork");
}
- if (Triple.isOSDarwin())
+ if (Triple.isOSDarwin()) {
CmdArgs.push_back("-analyzer-checker=osx");
+ CmdArgs.push_back(
+ "-analyzer-checker=security.insecureAPI.decodeValueOfObjCType");
+ }
+ else if (Triple.isOSFuchsia())
+ CmdArgs.push_back("-analyzer-checker=fuchsia");
CmdArgs.push_back("-analyzer-checker=deadcode");
@@ -3145,12 +3593,11 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
// This avoids having to monkey around further in cc1 other than to disable
// codeview if not running in a Windows environment. Perhaps even that
// decision should be made in the driver as well though.
- unsigned DWARFVersion = 0;
llvm::DebuggerKind DebuggerTuning = TC.getDefaultDebuggerTuning();
bool SplitDWARFInlining =
Args.hasFlag(options::OPT_fsplit_dwarf_inlining,
- options::OPT_fno_split_dwarf_inlining, true);
+ options::OPT_fno_split_dwarf_inlining, false);
Args.ClaimAllArgs(options::OPT_g_Group);
@@ -3198,11 +3645,16 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
}
// If a -gdwarf argument appeared, remember it.
- if (const Arg *A =
- Args.getLastArg(options::OPT_gdwarf_2, options::OPT_gdwarf_3,
- options::OPT_gdwarf_4, options::OPT_gdwarf_5))
- if (checkDebugInfoOption(A, Args, D, TC))
- DWARFVersion = DwarfVersionNum(A->getSpelling());
+ const Arg *GDwarfN = Args.getLastArg(
+ options::OPT_gdwarf_2, options::OPT_gdwarf_3, options::OPT_gdwarf_4,
+ options::OPT_gdwarf_5, options::OPT_gdwarf);
+ bool EmitDwarf = false;
+ if (GDwarfN) {
+ if (checkDebugInfoOption(GDwarfN, Args, D, TC))
+ EmitDwarf = true;
+ else
+ GDwarfN = nullptr;
+ }
if (const Arg *A = Args.getLastArg(options::OPT_gcodeview)) {
if (checkDebugInfoOption(A, Args, D, TC))
@@ -3211,18 +3663,36 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
// If the user asked for debug info but did not explicitly specify -gcodeview
// or -gdwarf, ask the toolchain for the default format.
- if (!EmitCodeView && DWARFVersion == 0 &&
+ if (!EmitCodeView && !EmitDwarf &&
DebugInfoKind != codegenoptions::NoDebugInfo) {
switch (TC.getDefaultDebugFormat()) {
case codegenoptions::DIF_CodeView:
EmitCodeView = true;
break;
case codegenoptions::DIF_DWARF:
- DWARFVersion = TC.GetDefaultDwarfVersion();
+ EmitDwarf = true;
break;
}
}
+ unsigned DWARFVersion = 0;
+ unsigned DefaultDWARFVersion = ParseDebugDefaultVersion(TC, Args);
+ if (EmitDwarf) {
+ // Start with the platform default DWARF version
+ DWARFVersion = TC.GetDefaultDwarfVersion();
+ assert(DWARFVersion && "toolchain default DWARF version must be nonzero");
+
+ // If the user specified a default DWARF version, that takes precedence
+ // over the platform default.
+ if (DefaultDWARFVersion)
+ DWARFVersion = DefaultDWARFVersion;
+
+ // Override with a user-specified DWARF version
+ if (GDwarfN)
+ if (auto ExplicitVersion = DwarfVersionNum(GDwarfN->getSpelling()))
+ DWARFVersion = ExplicitVersion;
+ }
+
// -gline-directives-only supported only for the DWARF debug info.
if (DWARFVersion == 0 && DebugInfoKind == codegenoptions::DebugDirectivesOnly)
DebugInfoKind = codegenoptions::NoDebugInfo;
@@ -3296,9 +3766,20 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
}
}
+ // Omit inline line tables if requested.
+ if (Args.hasFlag(options::OPT_gno_inline_line_tables,
+ options::OPT_ginline_line_tables, false)) {
+ CmdArgs.push_back("-gno-inline-line-tables");
+ }
+
// Adjust the debug info kind for the given toolchain.
TC.adjustDebugInfoKind(DebugInfoKind, Args);
+ // When emitting remarks, we need at least debug lines in the output.
+ if (willEmitRemarks(Args) &&
+ DebugInfoKind <= codegenoptions::DebugDirectivesOnly)
+ DebugInfoKind = codegenoptions::DebugLineTablesOnly;
+
RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, DWARFVersion,
DebuggerTuning);
@@ -3339,6 +3820,10 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
CmdArgs.push_back("-generate-arange-section");
}
+ if (Args.hasFlag(options::OPT_fforce_dwarf_frame,
+ options::OPT_fno_force_dwarf_frame, false))
+ CmdArgs.push_back("-fforce-dwarf-frame");
+
if (Args.hasFlag(options::OPT_fdebug_types_section,
options::OPT_fno_debug_types_section, false)) {
if (!T.isOSBinFormatELF()) {
@@ -3641,6 +4126,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fthinlto_index_EQ);
}
+ if (Args.getLastArg(options::OPT_fthin_link_bitcode_EQ))
+ Args.AddLastArg(CmdArgs, options::OPT_fthin_link_bitcode_EQ);
+
if (Args.getLastArg(options::OPT_save_temps_EQ))
Args.AddLastArg(CmdArgs, options::OPT_save_temps_EQ);
@@ -3653,7 +4141,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Disable all llvm IR level optimizations.
CmdArgs.push_back("-disable-llvm-passes");
- // Render target options such as -fuse-init-array on modern ELF platforms.
+ // Render target options.
TC.addClangTargetOptions(Args, CmdArgs, JA.getOffloadingDeviceKind());
// reject options that shouldn't be supported in bitcode
@@ -3718,6 +4206,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
RenderARMABI(Triple, Args, CmdArgs);
break;
case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_32:
case llvm::Triple::aarch64_be:
RenderAArch64ABI(Triple, Args, CmdArgs);
break;
@@ -4009,8 +4498,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
RenderFloatingPointOptions(TC, D, OFastEnabled, Args, CmdArgs);
if (Arg *A = Args.getLastArg(options::OPT_LongDouble_Group)) {
- if (TC.getArch() == llvm::Triple::x86 ||
- TC.getArch() == llvm::Triple::x86_64)
+ if (TC.getTriple().isX86())
A->render(Args, CmdArgs);
else if ((TC.getArch() == llvm::Triple::ppc || TC.getTriple().isPPC64()) &&
(A->getOption().getID() != options::OPT_mlong_double_80))
@@ -4097,6 +4585,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue());
}
+ if (Arg *A = Args.getLastArg(options::OPT_mtls_size_EQ)) {
+ StringRef Value = A->getValue();
+ unsigned TLSSize = 0;
+ Value.getAsInteger(10, TLSSize);
+ if (!Triple.isAArch64() || !Triple.isOSBinFormatELF())
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getOption().getName() << TripleStr;
+ if (TLSSize != 12 && TLSSize != 24 && TLSSize != 32 && TLSSize != 48)
+ D.Diag(diag::err_drv_invalid_int_value)
+ << A->getOption().getName() << Value;
+ Args.AddLastArg(CmdArgs, options::OPT_mtls_size_EQ);
+ }
+
// Add the target cpu
std::string CPU = getCPUName(Args, Triple, /*FromAs*/ false);
if (!CPU.empty()) {
@@ -4362,7 +4863,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (ShouldDisableDwarfDirectory(Args, TC))
CmdArgs.push_back("-fno-dwarf-directory-asm");
- if (ShouldDisableAutolink(Args, TC))
+ if (!ShouldEnableAutolink(Args, TC, JA))
CmdArgs.push_back("-fno-autolink");
// Add in -fdebug-compilation-dir if necessary.
@@ -4394,9 +4895,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_fexperimental_new_constant_interpreter))
CmdArgs.push_back("-fexperimental-new-constant-interpreter");
- if (Args.hasArg(options::OPT_fforce_experimental_new_constant_interpreter))
- CmdArgs.push_back("-fforce-experimental-new-constant-interpreter");
-
if (Arg *A = Args.getLastArg(options::OPT_fbracket_depth_EQ)) {
CmdArgs.push_back("-fbracket-depth");
CmdArgs.push_back(A->getValue());
@@ -4532,6 +5030,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fnoopenmp-use-tls");
Args.AddLastArg(CmdArgs, options::OPT_fopenmp_simd,
options::OPT_fno_openmp_simd);
+ Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_enable_irbuilder);
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ);
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_cuda_number_of_sm_EQ);
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_cuda_blocks_per_sm_EQ);
@@ -4576,11 +5075,50 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const XRayArgs &XRay = TC.getXRayArgs();
XRay.addArgs(TC, Args, CmdArgs, InputType);
- if (TC.SupportsProfiling())
+ if (Arg *A = Args.getLastArg(options::OPT_fpatchable_function_entry_EQ)) {
+ StringRef S0 = A->getValue(), S = S0;
+ unsigned Size, Start = 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())))
+ D.Diag(diag::err_drv_invalid_argument_to_option)
+ << S0 << A->getOption().getName();
+ else if (Start)
+ D.Diag(diag::err_drv_unsupported_fpatchable_function_entry_argument);
+ else
+ CmdArgs.push_back(Args.MakeArgString(A->getSpelling() + Twine(Size)));
+ }
+
+ if (TC.SupportsProfiling()) {
Args.AddLastArg(CmdArgs, options::OPT_pg);
- if (TC.SupportsProfiling())
- Args.AddLastArg(CmdArgs, options::OPT_mfentry);
+ llvm::Triple::ArchType Arch = TC.getArch();
+ if (Arg *A = Args.getLastArg(options::OPT_mfentry)) {
+ if (Arch == llvm::Triple::systemz || TC.getTriple().isX86())
+ 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_mnop_mcount)) {
+ if (Arch == llvm::Triple::systemz)
+ 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_mrecord_mcount)) {
+ if (Arch == llvm::Triple::systemz)
+ A->render(Args, CmdArgs);
+ else
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getAsString(Args) << TripleStr;
+ }
+ }
if (Args.getLastArg(options::OPT_fapple_kext) ||
(Args.hasArg(options::OPT_mkernel) && types::isCXX(InputType)))
@@ -4595,6 +5133,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_ftime_trace_granularity_EQ);
Args.AddLastArg(CmdArgs, options::OPT_ftrapv);
Args.AddLastArg(CmdArgs, options::OPT_malign_double);
+ Args.AddLastArg(CmdArgs, options::OPT_fno_temp_file);
if (Arg *A = Args.getLastArg(options::OPT_ftrapv_handler_EQ)) {
CmdArgs.push_back("-ftrapv-handler");
@@ -5112,66 +5651,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fapple-pragma-pack");
// Remarks can be enabled with any of the `-f.*optimization-record.*` flags.
- if (Args.hasFlag(options::OPT_fsave_optimization_record,
- options::OPT_foptimization_record_file_EQ,
- options::OPT_fno_save_optimization_record, false) ||
- Args.hasFlag(options::OPT_fsave_optimization_record_EQ,
- options::OPT_fno_save_optimization_record, false) ||
- Args.hasFlag(options::OPT_foptimization_record_passes_EQ,
- options::OPT_fno_save_optimization_record, false)) {
- CmdArgs.push_back("-opt-record-file");
-
- const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);
- if (A) {
- CmdArgs.push_back(A->getValue());
- } else {
- SmallString<128> F;
-
- if (Args.hasArg(options::OPT_c) || Args.hasArg(options::OPT_S)) {
- if (Arg *FinalOutput = Args.getLastArg(options::OPT_o))
- F = FinalOutput->getValue();
- }
-
- if (F.empty()) {
- // Use the input filename.
- F = llvm::sys::path::stem(Input.getBaseInput());
-
- // If we're compiling for an offload architecture (i.e. a CUDA device),
- // we need to make the file name for the device compilation different
- // from the host compilation.
- if (!JA.isDeviceOffloading(Action::OFK_None) &&
- !JA.isDeviceOffloading(Action::OFK_Host)) {
- llvm::sys::path::replace_extension(F, "");
- F += Action::GetOffloadingFileNamePrefix(JA.getOffloadingDeviceKind(),
- Triple.normalize());
- F += "-";
- F += JA.getOffloadingArch();
- }
- }
-
- std::string Extension = "opt.";
- if (const Arg *A =
- Args.getLastArg(options::OPT_fsave_optimization_record_EQ))
- Extension += A->getValue();
- else
- Extension += "yaml";
-
- llvm::sys::path::replace_extension(F, Extension);
- CmdArgs.push_back(Args.MakeArgString(F));
- }
-
- if (const Arg *A =
- Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) {
- CmdArgs.push_back("-opt-record-passes");
- CmdArgs.push_back(A->getValue());
- }
-
- if (const Arg *A =
- Args.getLastArg(options::OPT_fsave_optimization_record_EQ)) {
- CmdArgs.push_back("-opt-record-format");
- CmdArgs.push_back(A->getValue());
- }
- }
+ if (willEmitRemarks(Args) && checkRemarksOptions(D, Args, Triple))
+ renderRemarksOptions(Args, CmdArgs, Triple, Input, Output, JA);
bool RewriteImports = Args.hasFlag(options::OPT_frewrite_imports,
options::OPT_fno_rewrite_imports, false);
@@ -5331,6 +5812,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fcuda-short-ptr");
}
+ if (IsHIP)
+ CmdArgs.push_back("-fcuda-allow-variadic-functions");
+
// OpenMP offloading device jobs take the argument -fopenmp-host-ir-file-path
// to specify the result of the compile phase on the host, so the meaningful
// device declarations can be identified. Also, -fopenmp-is-device is passed
@@ -5395,7 +5879,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fwhole-program-vtables");
}
- bool DefaultsSplitLTOUnit = WholeProgramVTables || Sanitize.needsLTO();
+ bool DefaultsSplitLTOUnit =
+ (WholeProgramVTables || Sanitize.needsLTO()) &&
+ (D.getLTOMode() == LTOK_Full || TC.canSplitThinLTOUnit());
bool SplitLTOUnit =
Args.hasFlag(options::OPT_fsplit_lto_unit,
options::OPT_fno_split_lto_unit, DefaultsSplitLTOUnit);
@@ -5467,11 +5953,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// 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) {
+ if (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");
- CmdArgs.push_back("-enable-machine-outliner");
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-enable-machine-outliner");
}
} else {
// Disable all outlining behaviour.
@@ -5485,7 +5972,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
TC.getTriple().isOSBinFormatCOFF()) &&
!TC.getTriple().isPS4() &&
!TC.getTriple().isOSNetBSD() &&
- !Distro(D.getVFS()).IsGentoo() &&
+ !Distro(D.getVFS(), TC.getTriple()).IsGentoo() &&
!TC.getTriple().isAndroid() &&
TC.useIntegratedAs()))
CmdArgs.push_back("-faddrsig");
@@ -5503,8 +5990,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Output.getType() == types::TY_Dependencies) {
// Handled with other dependency code.
} else if (Output.isFilename()) {
- CmdArgs.push_back("-o");
- CmdArgs.push_back(Output.getFilename());
+ if (Output.getType() == clang::driver::types::TY_IFS_CPP ||
+ Output.getType() == clang::driver::types::TY_IFS) {
+ SmallString<128> OutputFilename(Output.getFilename());
+ llvm::sys::path::replace_extension(OutputFilename, "ifs");
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Args.MakeArgString(OutputFilename));
+ } else {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ }
} else {
assert(Output.isNothing() && "Invalid output.");
}
@@ -5538,6 +6033,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// fails, so that the main compilation's fallback to cl.exe runs.
C.addCommand(std::make_unique<ForceSuccessCommand>(JA, *this, 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));
} else {
C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
@@ -5872,8 +6371,7 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
}
unsigned VolatileOptionID;
- if (getToolChain().getArch() == llvm::Triple::x86_64 ||
- getToolChain().getArch() == llvm::Triple::x86)
+ if (getToolChain().getTriple().isX86())
VolatileOptionID = options::OPT__SLASH_volatile_ms;
else
VolatileOptionID = options::OPT__SLASH_volatile_iso;
@@ -5967,26 +6465,19 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
}
if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) {
- SmallVector<StringRef, 1> SplitArgs;
- StringRef(A->getValue()).split(SplitArgs, ",");
- bool Instrument = false;
- bool NoChecks = false;
- for (StringRef Arg : SplitArgs) {
- if (Arg.equals_lower("cf"))
- Instrument = true;
- else if (Arg.equals_lower("cf-"))
- Instrument = false;
- else if (Arg.equals_lower("nochecks"))
- NoChecks = true;
- else if (Arg.equals_lower("nochecks-"))
- NoChecks = false;
- else
- D.Diag(diag::err_drv_invalid_value) << A->getSpelling() << Arg;
- }
- // Currently there's no support emitting CFG instrumentation; the flag only
- // emits the table of address-taken functions.
- if (Instrument || NoChecks)
+ StringRef GuardArgs = A->getValue();
+ // The only valid options are "cf", "cf,nochecks", and "cf-".
+ if (GuardArgs.equals_lower("cf")) {
+ // Emit CFG instrumentation and the table of address-taken functions.
CmdArgs.push_back("-cfguard");
+ } else if (GuardArgs.equals_lower("cf,nochecks")) {
+ // Emit only the table of address-taken functions.
+ CmdArgs.push_back("-cfguard-no-checks");
+ } else if (GuardArgs.equals_lower("cf-")) {
+ // Do nothing, but we might want to emit a security warning in future.
+ } else {
+ D.Diag(diag::err_drv_invalid_value) << A->getSpelling() << GuardArgs;
+ }
}
}
@@ -6040,6 +6531,8 @@ void ClangAs::AddMIPSTargetArgs(const ArgList &Args,
void ClangAs::AddX86TargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
+ addX86AlignBranchArgs(getToolChain().getDriver(), Args, CmdArgs);
+
if (Arg *A = Args.getLastArg(options::OPT_masm_EQ)) {
StringRef Value = A->getValue();
if (Value == "intel" || Value == "att") {
@@ -6134,6 +6627,11 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
if (WantDebug)
DwarfVersion = DwarfVersionNum(A->getSpelling());
}
+
+ unsigned DefaultDwarfVersion = ParseDebugDefaultVersion(getToolChain(), Args);
+ if (DwarfVersion == 0)
+ DwarfVersion = DefaultDwarfVersion;
+
if (DwarfVersion == 0)
DwarfVersion = getToolChain().GetDefaultDwarfVersion();
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 10743559e0481..37ec734685706 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -11,12 +11,8 @@
#include "Arch/ARM.h"
#include "Arch/Mips.h"
#include "Arch/PPC.h"
-#include "Arch/RISCV.h"
-#include "Arch/Sparc.h"
#include "Arch/SystemZ.h"
#include "Arch/X86.h"
-#include "AMDGPU.h"
-#include "MSP430.h"
#include "HIP.h"
#include "Hexagon.h"
#include "InputInfo.h"
@@ -257,6 +253,7 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T,
return "";
case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_32:
case llvm::Triple::aarch64_be:
return aarch64::getAArch64TargetCPU(Args, T, A);
@@ -488,14 +485,6 @@ void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
if (!StatsFile.empty())
CmdArgs.push_back(
Args.MakeArgString(Twine("-plugin-opt=stats-file=") + StatsFile));
-
- getTargetFeatures(ToolChain, ToolChain.getTriple(), Args, CmdArgs,
- /* ForAS= */ false, /* ForLTOPlugin= */ true);
-
- StringRef ABIName = tools::getTargetABI(Args, ToolChain.getTriple());
- if (!ABIName.empty())
- CmdArgs.push_back(
- Args.MakeArgString(Twine("-plugin-opt=-target-abi=") + ABIName));
}
void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args,
@@ -1138,6 +1127,21 @@ unsigned tools::ParseFunctionAlignment(const ToolChain &TC,
return Value ? llvm::Log2_32_Ceil(std::min(Value, 65536u)) : Value;
}
+unsigned tools::ParseDebugDefaultVersion(const ToolChain &TC,
+ const ArgList &Args) {
+ const Arg *A = Args.getLastArg(options::OPT_fdebug_default_version);
+
+ if (!A)
+ return 0;
+
+ unsigned Value = 0;
+ if (StringRef(A->getValue()).getAsInteger(10, Value) || Value > 5 ||
+ Value < 2)
+ TC.getDriver().Diag(diag::err_drv_invalid_int_value)
+ << A->getAsString(Args) << A->getValue();
+ return Value;
+}
+
void tools::AddAssemblerKPIC(const ToolChain &ToolChain, const ArgList &Args,
ArgStringList &CmdArgs) {
llvm::Reloc::Model RelocationModel;
@@ -1205,7 +1209,10 @@ static void AddUnwindLibrary(const ToolChain &TC, const Driver &D,
break;
}
case ToolChain::UNW_CompilerRT:
- CmdArgs.push_back("-lunwind");
+ if (LGT == LibGccType::StaticLibGcc)
+ CmdArgs.push_back("-l:libunwind.a");
+ else
+ CmdArgs.push_back("-l:libunwind.so");
break;
}
@@ -1392,111 +1399,3 @@ void tools::addMultilibFlag(bool Enabled, const char *const Flag,
Multilib::flags_list &Flags) {
Flags.push_back(std::string(Enabled ? "+" : "-") + Flag);
}
-
-static void getWebAssemblyTargetFeatures(const ArgList &Args,
- std::vector<StringRef> &Features) {
- handleTargetFeaturesGroup(Args, Features, options::OPT_m_wasm_Features_Group);
-}
-
-void tools::getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
- const ArgList &Args, ArgStringList &CmdArgs, bool ForAS,
- bool ForLTOPlugin) {
-
- const Driver &D = TC.getDriver();
- std::vector<StringRef> Features;
- switch (Triple.getArch()) {
- default:
- break;
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- mips::getMIPSTargetFeatures(D, Triple, Args, Features);
- break;
-
- case llvm::Triple::arm:
- case llvm::Triple::armeb:
- case llvm::Triple::thumb:
- case llvm::Triple::thumbeb:
- arm::getARMTargetFeatures(TC, Triple, Args, CmdArgs, Features, ForAS);
- break;
-
- case llvm::Triple::ppc:
- case llvm::Triple::ppc64:
- case llvm::Triple::ppc64le:
- ppc::getPPCTargetFeatures(D, Triple, Args, Features);
- break;
- case llvm::Triple::riscv32:
- case llvm::Triple::riscv64:
- riscv::getRISCVTargetFeatures(D, Triple, Args, Features);
- break;
- case llvm::Triple::systemz:
- systemz::getSystemZTargetFeatures(Args, Features);
- break;
- case llvm::Triple::aarch64:
- case llvm::Triple::aarch64_be:
- aarch64::getAArch64TargetFeatures(D, Triple, Args, Features);
- break;
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- x86::getX86TargetFeatures(D, Triple, Args, Features);
- break;
- case llvm::Triple::hexagon:
- hexagon::getHexagonTargetFeatures(D, Args, Features);
- break;
- case llvm::Triple::wasm32:
- case llvm::Triple::wasm64:
- getWebAssemblyTargetFeatures(Args, Features);
- break;
- case llvm::Triple::sparc:
- case llvm::Triple::sparcel:
- case llvm::Triple::sparcv9:
- sparc::getSparcTargetFeatures(D, Args, Features);
- break;
- case llvm::Triple::r600:
- case llvm::Triple::amdgcn:
- amdgpu::getAMDGPUTargetFeatures(D, Args, Features);
- break;
- case llvm::Triple::msp430:
- msp430::getMSP430TargetFeatures(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;
- if (!ForLTOPlugin) {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back(Name.data());
- } else {
- CmdArgs.push_back(
- Args.MakeArgString(Twine("-plugin-opt=-mattr=") + Name));
- }
- }
-}
-
-StringRef tools::getTargetABI(const ArgList &Args, const llvm::Triple &Triple) {
- // TODO: Support the other target ABI
- switch (Triple.getArch()) {
- default:
- break;
- case llvm::Triple::riscv32:
- case llvm::Triple::riscv64:
- return tools::riscv::getRISCVABI(Args, Triple);
- break;
- }
- return StringRef();
-}
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h
index 79468e6b89262..84b9d2cf59b49 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.h
+++ b/clang/lib/Driver/ToolChains/CommonArgs.h
@@ -68,6 +68,9 @@ ParsePICArgs(const ToolChain &ToolChain, const llvm::opt::ArgList &Args);
unsigned ParseFunctionAlignment(const ToolChain &TC,
const llvm::opt::ArgList &Args);
+unsigned ParseDebugDefaultVersion(const ToolChain &TC,
+ const llvm::opt::ArgList &Args);
+
void AddAssemblerKPIC(const ToolChain &ToolChain,
const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);
@@ -118,14 +121,6 @@ SmallString<128> getStatsFileName(const llvm::opt::ArgList &Args,
void addMultilibFlag(bool Enabled, const char *const Flag,
Multilib::flags_list &Flags);
-StringRef getTargetABI(const llvm::opt::ArgList &Args,
- const llvm::Triple &Triple);
-
-void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs, bool ForAS,
- bool ForLTOPlugin = false);
-
} // end namespace tools
} // end namespace driver
} // end namespace clang
diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp
index 8c704a3078adc..02871d2ce411f 100644
--- a/clang/lib/Driver/ToolChains/Cuda.cpp
+++ b/clang/lib/Driver/ToolChains/Cuda.cpp
@@ -115,7 +115,8 @@ CudaInstallationDetector::CudaInstallationDetector(
for (const char *Ver : Versions)
Candidates.emplace_back(D.SysRoot + "/usr/local/cuda-" + Ver);
- if (Distro(D.getVFS()).IsDebian() || Distro(D.getVFS()).IsUbuntu())
+ Distro Dist(D.getVFS(), 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
Candidates.emplace_back(D.SysRoot + "/usr/lib/cuda");
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index ee08b8208d939..344a14fe1ea7c 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -19,6 +19,7 @@
#include "clang/Driver/SanitizerArgs.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/TargetParser.h"
@@ -57,6 +58,7 @@ llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
.Cases("armv7", "armv7em", "armv7k", "armv7m", llvm::Triple::arm)
.Cases("armv7s", "xscale", llvm::Triple::arm)
.Case("arm64", llvm::Triple::aarch64)
+ .Case("arm64_32", llvm::Triple::aarch64_32)
.Case("r600", llvm::Triple::r600)
.Case("amdgcn", llvm::Triple::amdgcn)
.Case("nvptx", llvm::Triple::nvptx)
@@ -122,8 +124,7 @@ void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
AddMachOArch(Args, CmdArgs);
// Use -force_cpusubtype_ALL on x86 by default.
- if (getToolChain().getArch() == llvm::Triple::x86 ||
- getToolChain().getArch() == llvm::Triple::x86_64 ||
+ if (getToolChain().getTriple().isX86() ||
Args.hasArg(options::OPT_force__cpusubtype__ALL))
CmdArgs.push_back("-force_cpusubtype_ALL");
@@ -334,7 +335,10 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
Args.AddAllArgs(CmdArgs, options::OPT_init);
// Add the deployment target.
- MachOTC.addMinVersionArgs(Args, CmdArgs);
+ if (!Version[0] || Version[0] >= 520)
+ MachOTC.addPlatformVersionArgs(Args, CmdArgs);
+ else
+ MachOTC.addMinVersionArgs(Args, CmdArgs);
Args.AddLastArg(CmdArgs, options::OPT_nomultidefs);
Args.AddLastArg(CmdArgs, options::OPT_multi__module);
@@ -737,7 +741,7 @@ Darwin::Darwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
CudaInstallation(D, Triple, Args) {}
types::ID MachO::LookupTypeForExtension(StringRef Ext) const {
- types::ID Ty = types::lookupTypeForExtension(Ext);
+ types::ID Ty = ToolChain::LookupTypeForExtension(Ext);
// Darwin always preprocesses assembly files (unless -x is used explicitly).
if (Ty == types::TY_PP_Asm)
@@ -831,6 +835,9 @@ StringRef MachO::getMachOArchName(const ArgList &Args) const {
default:
return getDefaultUniversalArchName();
+ case llvm::Triple::aarch64_32:
+ return "arm64_32";
+
case llvm::Triple::aarch64:
return "arm64";
@@ -1061,7 +1068,6 @@ StringRef Darwin::getPlatformFamily() const {
StringRef Darwin::getSDKName(StringRef isysroot) {
// Assume SDK has path: SOME_PATH/SDKs/PlatformXX.YY.sdk
- llvm::sys::path::const_iterator SDKDir;
auto BeginSDK = llvm::sys::path::begin(isysroot);
auto EndSDK = llvm::sys::path::end(isysroot);
for (auto IT = BeginSDK; IT != EndSDK; ++IT) {
@@ -1110,6 +1116,19 @@ static void addExportedSymbol(ArgStringList &CmdArgs, const char *Symbol) {
CmdArgs.push_back(Symbol);
}
+/// Add a sectalign directive for \p Segment and \p Section to the maximum
+/// expected page size for Darwin.
+///
+/// On iPhone 6+ the max supported page size is 16K. On macOS, the max is 4K.
+/// Use a common alignment constant (16K) for now, and reduce the alignment on
+/// macOS if it proves important.
+static void addSectalignToPage(const ArgList &Args, ArgStringList &CmdArgs,
+ StringRef Segment, StringRef Section) {
+ for (const char *A : {"-sectalign", Args.MakeArgString(Segment),
+ Args.MakeArgString(Section), "0x4000"})
+ CmdArgs.push_back(A);
+}
+
void Darwin::addProfileRTLibs(const ArgList &Args,
ArgStringList &CmdArgs) const {
if (!needsProfileRT(Args)) return;
@@ -1117,11 +1136,13 @@ void Darwin::addProfileRTLibs(const ArgList &Args,
AddLinkRuntimeLib(Args, CmdArgs, "profile",
RuntimeLinkOptions(RLO_AlwaysLink | RLO_FirstLink));
+ bool ForGCOV = needsGCovInstrumentation(Args);
+
// If we have a symbol export directive and we're linking in the profile
// runtime, automatically export symbols necessary to implement some of the
// runtime's functionality.
if (hasExportSymbolDirective(Args)) {
- if (needsGCovInstrumentation(Args)) {
+ if (ForGCOV) {
addExportedSymbol(CmdArgs, "___gcov_flush");
addExportedSymbol(CmdArgs, "_flush_fn_list");
addExportedSymbol(CmdArgs, "_writeout_fn_list");
@@ -1131,6 +1152,24 @@ void Darwin::addProfileRTLibs(const ArgList &Args,
}
addExportedSymbol(CmdArgs, "_lprofDirMode");
}
+
+ // Align __llvm_prf_{cnts,data} sections to the maximum expected page
+ // alignment. This allows profile counters to be mmap()'d to disk. Note that
+ // it's not enough to just page-align __llvm_prf_cnts: the following section
+ // must also be page-aligned so that its data is not clobbered by mmap().
+ //
+ // The section alignment is only needed when continuous profile sync is
+ // enabled, but this is expected to be the default in Xcode. Specifying the
+ // extra alignment also allows the same binary to be used with/without sync
+ // enabled.
+ if (!ForGCOV) {
+ for (auto IPSK : {llvm::IPSK_cnts, llvm::IPSK_data}) {
+ addSectalignToPage(
+ Args, CmdArgs, "__DATA",
+ llvm::getInstrProfSectionName(IPSK, llvm::Triple::MachO,
+ /*AddSegmentInfo=*/false));
+ }
+ }
}
void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args,
@@ -1493,8 +1532,8 @@ getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver,
Targets[Darwin::TvOS] = "";
} else {
// Don't allow conflicts in any other platform.
- int FirstTarget = llvm::array_lengthof(Targets);
- for (int I = 0; I != llvm::array_lengthof(Targets); ++I) {
+ unsigned FirstTarget = llvm::array_lengthof(Targets);
+ for (unsigned I = 0; I != llvm::array_lengthof(Targets); ++I) {
if (Targets[I].empty())
continue;
if (FirstTarget == llvm::array_lengthof(Targets))
@@ -1607,7 +1646,7 @@ inferDeploymentTargetFromArch(DerivedArgList &Args, const Darwin &Toolchain,
if (MachOArchName == "armv7" || MachOArchName == "armv7s" ||
MachOArchName == "arm64")
OSTy = llvm::Triple::IOS;
- else if (MachOArchName == "armv7k")
+ else if (MachOArchName == "armv7k" || MachOArchName == "arm64_32")
OSTy = llvm::Triple::WatchOS;
else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
MachOArchName != "armv7em")
@@ -1796,9 +1835,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
DarwinEnvironmentKind Environment = OSTarget->getEnvironment();
// Recognize iOS targets with an x86 architecture as the iOS simulator.
if (Environment == NativeEnvironment && Platform != MacOS &&
- OSTarget->canInferSimulatorFromArch() &&
- (getTriple().getArch() == llvm::Triple::x86 ||
- getTriple().getArch() == llvm::Triple::x86_64))
+ OSTarget->canInferSimulatorFromArch() && getTriple().isX86())
Environment = Simulator;
setTarget(Platform, Environment, Major, Minor, Micro);
@@ -2194,8 +2231,7 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
}
}
- if (getTriple().getArch() == llvm::Triple::x86 ||
- getTriple().getArch() == llvm::Triple::x86_64)
+ if (getTriple().isX86())
if (!Args.hasArgNoClaim(options::OPT_mtune_EQ))
DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_mtune_EQ),
"core2");
@@ -2451,7 +2487,7 @@ bool MachO::isPICDefaultForced() const {
bool MachO::SupportsProfiling() const {
// Profiling instrumentation is only supported on x86.
- return getArch() == llvm::Triple::x86 || getArch() == llvm::Triple::x86_64;
+ return getTriple().isX86();
}
void Darwin::addMinVersionArgs(const ArgList &Args,
@@ -2478,6 +2514,45 @@ void Darwin::addMinVersionArgs(const ArgList &Args,
CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
}
+static const char *getPlatformName(Darwin::DarwinPlatformKind Platform,
+ Darwin::DarwinEnvironmentKind Environment) {
+ switch (Platform) {
+ case Darwin::MacOS:
+ return "macos";
+ case Darwin::IPhoneOS:
+ if (Environment == Darwin::NativeEnvironment ||
+ Environment == Darwin::Simulator)
+ return "ios";
+ // FIXME: Add macCatalyst support here ("\"mac catalyst\"").
+ llvm_unreachable("macCatalyst isn't yet supported");
+ case Darwin::TvOS:
+ return "tvos";
+ case Darwin::WatchOS:
+ return "watchos";
+ }
+ llvm_unreachable("invalid platform");
+}
+
+void Darwin::addPlatformVersionArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const {
+ // -platform_version <platform> <target_version> <sdk_version>
+ // Both the target and SDK version support only up to 3 components.
+ CmdArgs.push_back("-platform_version");
+ std::string PlatformName = getPlatformName(TargetPlatform, TargetEnvironment);
+ if (TargetEnvironment == Darwin::Simulator)
+ PlatformName += "-simulator";
+ CmdArgs.push_back(Args.MakeArgString(PlatformName));
+ VersionTuple TargetVersion = getTargetVersion().withoutBuild();
+ CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
+ if (SDKInfo) {
+ VersionTuple SDKVersion = SDKInfo->getVersion().withoutBuild();
+ CmdArgs.push_back(Args.MakeArgString(SDKVersion.getAsString()));
+ } else {
+ // Use a blank SDK version if it's not present.
+ CmdArgs.push_back("0.0.0");
+ }
+}
+
void Darwin::addStartObjectFileArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
// Derived from startfile spec.
diff --git a/clang/lib/Driver/ToolChains/Darwin.h b/clang/lib/Driver/ToolChains/Darwin.h
index 2dc7c85880f73..1b193a4c4eb96 100644
--- a/clang/lib/Driver/ToolChains/Darwin.h
+++ b/clang/lib/Driver/ToolChains/Darwin.h
@@ -167,6 +167,10 @@ public:
virtual void addMinVersionArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const {}
+ virtual void addPlatformVersionArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const {
+ }
+
/// On some iOS platforms, kernel and kernel modules were built statically. Is
/// this such a target?
virtual bool isKernelStatic() const { return false; }
@@ -258,6 +262,9 @@ public:
return "";
}
+ // Darwin toolchain uses legacy thin LTO API, which is not
+ // capable of unit splitting.
+ bool canSplitThinLTOUnit() const override { return false; }
/// }
};
@@ -311,6 +318,9 @@ public:
void addMinVersionArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
+ void addPlatformVersionArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+
void addStartObjectFileArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
new file mode 100644
index 0000000000000..9b9eb81fa111d
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -0,0 +1,79 @@
+//===-- Flang.cpp - Flang+LLVM 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 "Flang.h"
+#include "CommonArgs.h"
+
+#include "clang/Driver/Options.h"
+
+#include <cassert>
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+void Flang::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const ArgList &Args, const char *LinkingOutput) const {
+ const auto &TC = getToolChain();
+ const llvm::Triple &Triple = TC.getEffectiveTriple();
+ const std::string &TripleStr = Triple.getTriple();
+
+ ArgStringList CmdArgs;
+
+ CmdArgs.push_back("-fc1");
+
+ CmdArgs.push_back("-triple");
+ CmdArgs.push_back(Args.MakeArgString(TripleStr));
+
+ if (isa<PreprocessJobAction>(JA)) {
+ CmdArgs.push_back("-E");
+ } else if (isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) {
+ if (JA.getType() == types::TY_Nothing) {
+ CmdArgs.push_back("-fsyntax-only");
+ } else if (JA.getType() == types::TY_AST) {
+ CmdArgs.push_back("-emit-ast");
+ } else if (JA.getType() == types::TY_LLVM_IR ||
+ JA.getType() == types::TY_LTO_IR) {
+ CmdArgs.push_back("-emit-llvm");
+ } else if (JA.getType() == types::TY_LLVM_BC ||
+ JA.getType() == types::TY_LTO_BC) {
+ CmdArgs.push_back("-emit-llvm-bc");
+ } else if (JA.getType() == types::TY_PP_Asm) {
+ CmdArgs.push_back("-S");
+ } else {
+ assert(false && "Unexpected output type!");
+ }
+ } else if (isa<AssembleJobAction>(JA)) {
+ CmdArgs.push_back("-emit-obj");
+ } else {
+ assert(false && "Unexpected action class for Flang tool.");
+ }
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ const InputInfo &Input = Inputs[0];
+ assert(Input.isFilename() && "Invalid input.");
+ CmdArgs.push_back(Input.getFilename());
+
+ 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));
+}
+
+Flang::Flang(const ToolChain &TC)
+ : Tool("flang", "flang frontend", TC, RF_Full) {}
+
+Flang::~Flang() {}
diff --git a/clang/lib/Driver/ToolChains/Flang.h b/clang/lib/Driver/ToolChains/Flang.h
new file mode 100644
index 0000000000000..19e3a8c28f7e4
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/Flang.h
@@ -0,0 +1,46 @@
+//===--- Flang.h - Flang Tool and ToolChain Implementations ====-*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_FLANG_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_FLANG_H
+
+#include "clang/Driver/Tool.h"
+#include "clang/Driver/Action.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/ToolChain.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/Compiler.h"
+
+namespace clang {
+namespace driver {
+
+namespace tools {
+
+/// Flang compiler tool.
+class LLVM_LIBRARY_VISIBILITY Flang : public Tool {
+public:
+ Flang(const ToolChain &TC);
+ ~Flang() override;
+
+ bool hasGoodDiagnostics() const override { return true; }
+ bool hasIntegratedAssembler() const override { return true; }
+ bool hasIntegratedCPP() const override { return true; }
+ bool canEmitIR() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
+} // end namespace tools
+
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_FLANG_H
diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp
index 7c891a24ba304..c5c6f530f48c0 100644
--- a/clang/lib/Driver/ToolChains/FreeBSD.cpp
+++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp
@@ -12,6 +12,7 @@
#include "Arch/Sparc.h"
#include "CommonArgs.h"
#include "clang/Driver/Compilation.h"
+#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "llvm/Option/ArgList.h"
@@ -30,6 +31,7 @@ void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const char *LinkingOutput) const {
claimNoWarnArgs(Args);
ArgStringList CmdArgs;
+ const auto &D = getToolChain().getDriver();
// When building 32-bit code on FreeBSD/amd64, we have to explicitly
// instruct as in the base system to assemble 32-bit code.
@@ -103,6 +105,19 @@ void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ,
+ options::OPT_fdebug_prefix_map_EQ)) {
+ StringRef Map = A->getValue();
+ if (Map.find('=') == StringRef::npos)
+ D.Diag(diag::err_drv_invalid_argument_to_option)
+ << Map << A->getOption().getName();
+ else {
+ CmdArgs.push_back(Args.MakeArgString("--debug-prefix-map"));
+ CmdArgs.push_back(Args.MakeArgString(Map));
+ }
+ A->claim();
+ }
+
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
CmdArgs.push_back("-o");
@@ -155,11 +170,10 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back("/libexec/ld-elf.so.1");
}
- if (ToolChain.getTriple().getOSMajorVersion() >= 9) {
- if (Arch == llvm::Triple::arm || Arch == llvm::Triple::sparc ||
- Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) {
+ const llvm::Triple &T = ToolChain.getTriple();
+ if (T.getOSMajorVersion() >= 9) {
+ if (Arch == llvm::Triple::arm || Arch == llvm::Triple::sparc || T.isX86())
CmdArgs.push_back("--hash-style=both");
- }
}
CmdArgs.push_back("--enable-new-dtags");
}
@@ -397,6 +411,11 @@ void FreeBSD::AddCXXStdlibLibArgs(const ArgList &Args,
}
}
+void FreeBSD::AddCudaIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
+}
+
Tool *FreeBSD::buildAssembler() const {
return new tools::freebsd::Assembler(*this);
}
@@ -420,6 +439,8 @@ llvm::ExceptionHandling FreeBSD::GetExceptionModel(const ArgList &Args) const {
bool FreeBSD::HasNativeLLVMSupport() const { return true; }
+bool FreeBSD::IsUnwindTablesDefault(const ArgList &Args) const { return true; }
+
bool FreeBSD::isPIEDefault() const { return getSanitizerArgs().requiresPIE(); }
SanitizerMask FreeBSD::getSupportedSanitizers() const {
@@ -445,3 +466,12 @@ SanitizerMask FreeBSD::getSupportedSanitizers() const {
Res |= SanitizerKind::Memory;
return Res;
}
+
+void FreeBSD::addClangTargetOptions(const ArgList &DriverArgs,
+ ArgStringList &CC1Args,
+ Action::OffloadKind) const {
+ if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
+ options::OPT_fno_use_init_array,
+ getTriple().getOSMajorVersion() >= 12))
+ CC1Args.push_back("-fno-use-init-array");
+}
diff --git a/clang/lib/Driver/ToolChains/FreeBSD.h b/clang/lib/Driver/ToolChains/FreeBSD.h
index d17b3808ffacc..84bdbfd9a3125 100644
--- a/clang/lib/Driver/ToolChains/FreeBSD.h
+++ b/clang/lib/Driver/ToolChains/FreeBSD.h
@@ -64,15 +64,22 @@ public:
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;
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;
unsigned GetDefaultDwarfVersion() const override;
// Until dtrace (via CTF) and LLDB can deal with distributed debug info,
// FreeBSD defaults to standalone/full debug info.
bool GetDefaultStandaloneDebug() const override { return true; }
+ void
+ addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadKind) const override;
protected:
Tool *buildAssembler() const override;
diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp
index e7d38ff9f227b..808d0408d0d4c 100644
--- a/clang/lib/Driver/ToolChains/Fuchsia.cpp
+++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp
@@ -46,6 +46,9 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// handled somewhere else.
Args.ClaimAllArgs(options::OPT_w);
+ CmdArgs.push_back("-z");
+ CmdArgs.push_back("now");
+
const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
if (llvm::sys::path::filename(Exec).equals_lower("ld.lld") ||
llvm::sys::path::stem(Exec).equals_lower("ld.lld")) {
@@ -224,7 +227,7 @@ Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple,
std::string Fuchsia::ComputeEffectiveClangTriple(const ArgList &Args,
types::ID InputType) const {
llvm::Triple Triple(ComputeLLVMTriple(Args, InputType));
- return (Triple.getArchName() + "-" + Triple.getOSName()).str();
+ return Triple.str();
}
Tool *Fuchsia::buildLinker() const {
@@ -258,9 +261,9 @@ Fuchsia::GetCXXStdlibType(const ArgList &Args) const {
void Fuchsia::addClangTargetOptions(const ArgList &DriverArgs,
ArgStringList &CC1Args,
Action::OffloadKind) const {
- if (DriverArgs.hasFlag(options::OPT_fuse_init_array,
- options::OPT_fno_use_init_array, true))
- CC1Args.push_back("-fuse-init-array");
+ if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
+ options::OPT_fno_use_init_array, true))
+ CC1Args.push_back("-fno-use-init-array");
}
void Fuchsia::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
@@ -343,5 +346,17 @@ SanitizerMask Fuchsia::getSupportedSanitizers() const {
}
SanitizerMask Fuchsia::getDefaultSanitizers() const {
- return SanitizerKind::SafeStack;
+ SanitizerMask Res;
+ switch (getTriple().getArch()) {
+ case llvm::Triple::aarch64:
+ Res |= SanitizerKind::ShadowCallStack;
+ break;
+ case llvm::Triple::x86_64:
+ Res |= SanitizerKind::SafeStack;
+ break;
+ default:
+ // TODO: Enable SafeStack on RISC-V once tested.
+ break;
+ }
+ return Res;
}
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index c302a31cd2e10..da197e476621a 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -709,11 +709,9 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
StringRef ABIName = riscv::getRISCVABI(Args, getToolChain().getTriple());
CmdArgs.push_back("-mabi");
CmdArgs.push_back(ABIName.data());
- if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
- StringRef MArch = A->getValue();
- CmdArgs.push_back("-march");
- CmdArgs.push_back(MArch.data());
- }
+ StringRef MArchName = riscv::getRISCVArch(Args, getToolChain().getTriple());
+ CmdArgs.push_back("-march");
+ CmdArgs.push_back(MArchName.data());
break;
}
case llvm::Triple::sparc:
@@ -864,12 +862,25 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
case llvm::Triple::systemz: {
// Always pass an -march option, since our default of z10 is later
// than the GNU assembler's default.
- StringRef CPUName = systemz::getSystemZTargetCPU(Args);
+ std::string CPUName = systemz::getSystemZTargetCPU(Args);
CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName));
break;
}
}
+ for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ,
+ options::OPT_fdebug_prefix_map_EQ)) {
+ StringRef Map = A->getValue();
+ if (Map.find('=') == StringRef::npos)
+ D.Diag(diag::err_drv_invalid_argument_to_option)
+ << Map << A->getOption().getName();
+ else {
+ CmdArgs.push_back(Args.MakeArgString("--debug-prefix-map"));
+ CmdArgs.push_back(Args.MakeArgString(Map));
+ }
+ A->claim();
+ }
+
Args.AddAllArgs(CmdArgs, options::OPT_I);
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
@@ -1393,7 +1404,8 @@ bool clang::driver::findMIPSMultilibs(const Driver &D,
addMultilibFlag(CPUName == "mips32r6", "march=mips32r6", Flags);
addMultilibFlag(CPUName == "mips64", "march=mips64", Flags);
addMultilibFlag(CPUName == "mips64r2" || CPUName == "mips64r3" ||
- CPUName == "mips64r5" || CPUName == "octeon",
+ CPUName == "mips64r5" || CPUName == "octeon" ||
+ CPUName == "octeon+",
"march=mips64r2", Flags);
addMultilibFlag(CPUName == "mips64r6", "march=mips64r6", Flags);
addMultilibFlag(isMicroMips(Args), "mmicromips", Flags);
@@ -1504,9 +1516,65 @@ static bool findMSP430Multilibs(const Driver &D,
return false;
}
+static void findRISCVBareMetalMultilibs(const Driver &D,
+ const llvm::Triple &TargetTriple,
+ StringRef Path, const ArgList &Args,
+ DetectedMultilibs &Result) {
+ FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
+ struct RiscvMultilib {
+ StringRef march;
+ StringRef mabi;
+ };
+ // currently only support the set of multilibs like riscv-gnu-toolchain does.
+ // TODO: support MULTILIB_REUSE
+ SmallVector<RiscvMultilib, 8> RISCVMultilibSet = {
+ {"rv32i", "ilp32"}, {"rv32im", "ilp32"}, {"rv32iac", "ilp32"},
+ {"rv32imac", "ilp32"}, {"rv32imafc", "ilp32f"}, {"rv64imac", "lp64"},
+ {"rv64imafdc", "lp64d"}};
+
+ std::vector<Multilib> Ms;
+ for (auto Element : RISCVMultilibSet) {
+ // multilib path rule is ${march}/${mabi}
+ Ms.emplace_back(
+ makeMultilib((Twine(Element.march) + "/" + Twine(Element.mabi)).str())
+ .flag(Twine("+march=", Element.march).str())
+ .flag(Twine("+mabi=", Element.mabi).str()));
+ }
+ MultilibSet RISCVMultilibs =
+ MultilibSet()
+ .Either(ArrayRef<Multilib>(Ms))
+ .FilterOut(NonExistent)
+ .setFilePathsCallback([](const Multilib &M) {
+ return std::vector<std::string>(
+ {M.gccSuffix(),
+ "/../../../../riscv64-unknown-elf/lib" + M.gccSuffix(),
+ "/../../../../riscv32-unknown-elf/lib" + M.gccSuffix()});
+ });
+
+
+ Multilib::flags_list Flags;
+ llvm::StringSet<> Added_ABIs;
+ StringRef ABIName = tools::riscv::getRISCVABI(Args, TargetTriple);
+ StringRef MArch = tools::riscv::getRISCVArch(Args, TargetTriple);
+ for (auto Element : RISCVMultilibSet) {
+ addMultilibFlag(MArch == Element.march,
+ Twine("march=", Element.march).str().c_str(), Flags);
+ if (!Added_ABIs.count(Element.mabi)) {
+ Added_ABIs.insert(Element.mabi);
+ addMultilibFlag(ABIName == Element.mabi,
+ Twine("mabi=", Element.mabi).str().c_str(), Flags);
+ }
+ }
+
+ if (RISCVMultilibs.select(Flags, Result.SelectedMultilib))
+ Result.Multilibs = RISCVMultilibs;
+}
+
static void findRISCVMultilibs(const Driver &D,
const llvm::Triple &TargetTriple, StringRef Path,
const ArgList &Args, DetectedMultilibs &Result) {
+ if (TargetTriple.getOS() == llvm::Triple::UnknownOS)
+ return findRISCVBareMetalMultilibs(D, TargetTriple, Path, Args, Result);
FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
Multilib Ilp32 = makeMultilib("lib32/ilp32").flag("+m32").flag("+mabi=ilp32");
@@ -2002,7 +2070,9 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
static const char *const PPCLibDirs[] = {"/lib32", "/lib"};
static const char *const PPCTriples[] = {
"powerpc-linux-gnu", "powerpc-unknown-linux-gnu", "powerpc-linux-gnuspe",
- "powerpc-suse-linux", "powerpc-montavista-linuxspe"};
+ // On 32-bit PowerPC systems running SUSE Linux, gcc is configured as a
+ // 64-bit compiler which defaults to "-m32", hence "powerpc64-suse-linux".
+ "powerpc64-suse-linux", "powerpc-montavista-linuxspe"};
static const char *const PPC64LibDirs[] = {"/lib64", "/lib"};
static const char *const PPC64Triples[] = {
"powerpc64-linux-gnu", "powerpc64-unknown-linux-gnu",
@@ -2545,9 +2615,6 @@ bool Generic_GCC::isPICDefault() const {
switch (getArch()) {
case llvm::Triple::x86_64:
return getTriple().isOSWindows();
- case llvm::Triple::ppc64:
- // Big endian PPC is PIC by default
- return !getTriple().isOSBinFormatMachO() && !getTriple().isMacOSX();
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
return true;
@@ -2616,19 +2683,49 @@ void Generic_GCC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
}
}
-void
-Generic_GCC::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const {
- // FIXME: The Linux behavior would probaby be a better approach here.
- addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/usr/include/c++/v1");
+static std::string DetectLibcxxIncludePath(llvm::vfs::FileSystem &vfs,
+ StringRef base) {
+ std::error_code EC;
+ int MaxVersion = 0;
+ std::string MaxVersionString;
+ for (llvm::vfs::directory_iterator LI = vfs.dir_begin(base, EC), LE;
+ !EC && LI != LE; LI = LI.increment(EC)) {
+ StringRef VersionText = llvm::sys::path::filename(LI->path());
+ int Version;
+ if (VersionText[0] == 'v' &&
+ !VersionText.slice(1, StringRef::npos).getAsInteger(10, Version)) {
+ if (Version > MaxVersion) {
+ MaxVersion = Version;
+ MaxVersionString = VersionText;
+ }
+ }
+ }
+ return MaxVersion ? (base + "/" + MaxVersionString).str() : "";
}
void
-Generic_GCC::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const {
- // By default, we don't assume we know where libstdc++ might be installed.
- // FIXME: If we have a valid GCCInstallation, use it.
+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))
+ return false;
+ addSystemInclude(DriverArgs, CC1Args, IncludePath);
+ return true;
+ };
+ // Android never uses the libc++ headers installed alongside the toolchain,
+ // which are generally incompatible with the NDK libraries anyway.
+ if (!getTriple().isAndroid())
+ if (AddIncludePath(getDriver().Dir + "/../include/c++"))
+ return;
+ // If this is a development, non-installed, clang, libcxx will
+ // not be found at ../include/c++ but it likely to be found at
+ // one of the following two locations:
+ if (AddIncludePath(SysRoot + "/usr/local/include/c++"))
+ return;
+ if (AddIncludePath(SysRoot + "/usr/include/c++"))
+ return;
}
/// Helper to add the variant paths of a libstdc++ installation.
@@ -2664,6 +2761,60 @@ bool Generic_GCC::addLibStdCXXIncludePaths(
return true;
}
+bool
+Generic_GCC::addGCCLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ // Use GCCInstallation to know where libstdc++ headers are installed.
+ if (!GCCInstallation.isValid())
+ return false;
+
+ // By default, look for the C++ headers in an include directory adjacent to
+ // the lib directory of the GCC installation. Note that this is expect to be
+ // equivalent to '/usr/include/c++/X.Y' in almost all cases.
+ StringRef LibDir = GCCInstallation.getParentLibPath();
+ StringRef InstallDir = GCCInstallation.getInstallPath();
+ StringRef TripleStr = GCCInstallation.getTriple().str();
+ const Multilib &Multilib = GCCInstallation.getMultilib();
+ const std::string GCCMultiarchTriple = getMultiarchTriple(
+ getDriver(), GCCInstallation.getTriple(), getDriver().SysRoot);
+ const std::string TargetMultiarchTriple =
+ getMultiarchTriple(getDriver(), getTriple(), getDriver().SysRoot);
+ const GCCVersion &Version = GCCInstallation.getVersion();
+
+ // The primary search for libstdc++ supports multiarch variants.
+ if (addLibStdCXXIncludePaths(LibDir.str() + "/../include",
+ "/c++/" + Version.Text, TripleStr,
+ GCCMultiarchTriple, TargetMultiarchTriple,
+ Multilib.includeSuffix(), DriverArgs, CC1Args))
+ return true;
+
+ // Otherwise, fall back on a bunch of options which don't use multiarch
+ // layouts for simplicity.
+ const std::string LibStdCXXIncludePathCandidates[] = {
+ // Gentoo is weird and places its headers inside the GCC install,
+ // so if the first attempt to find the headers fails, try these patterns.
+ InstallDir.str() + "/include/g++-v" + Version.Text,
+ InstallDir.str() + "/include/g++-v" + Version.MajorStr + "." +
+ Version.MinorStr,
+ InstallDir.str() + "/include/g++-v" + Version.MajorStr,
+ };
+
+ for (const auto &IncludePath : LibStdCXXIncludePathCandidates) {
+ if (addLibStdCXXIncludePaths(IncludePath, /*Suffix*/ "", TripleStr,
+ /*GCCMultiarchTriple*/ "",
+ /*TargetMultiarchTriple*/ "",
+ Multilib.includeSuffix(), DriverArgs, CC1Args))
+ return true;
+ }
+ return false;
+}
+
+void
+Generic_GCC::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args);
+}
+
llvm::opt::DerivedArgList *
Generic_GCC::TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef,
Action::OffloadKind DeviceOffloadKind) const {
@@ -2712,23 +2863,7 @@ void Generic_ELF::anchor() {}
void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs,
ArgStringList &CC1Args,
Action::OffloadKind) const {
- const Generic_GCC::GCCVersion &V = GCCInstallation.getVersion();
- bool UseInitArrayDefault =
- getTriple().getArch() == llvm::Triple::aarch64 ||
- getTriple().getArch() == llvm::Triple::aarch64_be ||
- (getTriple().isOSFreeBSD() &&
- getTriple().getOSMajorVersion() >= 12) ||
- (getTriple().getOS() == llvm::Triple::Linux &&
- ((!GCCInstallation.isValid() || !V.isOlderThan(4, 7, 0)) ||
- getTriple().isAndroid())) ||
- getTriple().getOS() == llvm::Triple::NaCl ||
- (getTriple().getVendor() == llvm::Triple::MipsTechnologies &&
- !getTriple().hasEnvironment()) ||
- getTriple().getOS() == llvm::Triple::Solaris ||
- getTriple().getArch() == llvm::Triple::riscv32 ||
- getTriple().getArch() == llvm::Triple::riscv64;
-
- if (DriverArgs.hasFlag(options::OPT_fuse_init_array,
- options::OPT_fno_use_init_array, UseInitArrayDefault))
- CC1Args.push_back("-fuse-init-array");
+ if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
+ options::OPT_fno_use_init_array, true))
+ CC1Args.push_back("-fno-use-init-array");
}
diff --git a/clang/lib/Driver/ToolChains/Gnu.h b/clang/lib/Driver/ToolChains/Gnu.h
index 3bb38c498b35d..083f74c054774 100644
--- a/clang/lib/Driver/ToolChains/Gnu.h
+++ b/clang/lib/Driver/ToolChains/Gnu.h
@@ -300,6 +300,11 @@ protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
+ virtual std::string getMultiarchTriple(const Driver &D,
+ const llvm::Triple &TargetTriple,
+ StringRef SysRoot) const
+ { return TargetTriple.str(); }
+
/// \name ToolChain Implementation Helper Functions
/// @{
@@ -322,6 +327,10 @@ protected:
addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const;
+ bool
+ addGCCLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+
bool addLibStdCXXIncludePaths(Twine Base, Twine Suffix, StringRef GCCTriple,
StringRef GCCMultiarchTriple,
StringRef TargetMultiarchTriple,
diff --git a/clang/lib/Driver/ToolChains/HIP.cpp b/clang/lib/Driver/ToolChains/HIP.cpp
index ad9384df6a242..f89e648948aba 100644
--- a/clang/lib/Driver/ToolChains/HIP.cpp
+++ b/clang/lib/Driver/ToolChains/HIP.cpp
@@ -62,6 +62,34 @@ static const char *getOutputFileName(Compilation &C, StringRef Base,
}
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(
@@ -93,25 +121,7 @@ const char *AMDGCN::Linker::constructOptCommand(
// The input to opt is the output from llvm-link.
OptArgs.push_back(InputFileName);
// Pass optimization arg to opt.
- 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)) {
- // -Os, -Oz, and -O(anything else) map to -O2
- OOpt = llvm::StringSwitch<const char *>(A->getValue())
- .Case("1", "1")
- .Case("2", "2")
- .Case("3", "3")
- .Case("s", "2")
- .Case("z", "2")
- .Default("2");
- }
- OptArgs.push_back(Args.MakeArgString("-O" + OOpt));
- }
+ addOptLevelArgs(Args, OptArgs);
OptArgs.push_back("-mtriple=amdgcn-amd-amdhsa");
OptArgs.push_back(Args.MakeArgString("-mcpu=" + SubArchName));
@@ -136,10 +146,15 @@ const char *AMDGCN::Linker::constructLlcCommand(
llvm::StringRef OutputFilePrefix, const char *InputFileName,
bool OutputIsAsm) const {
// Construct llc command.
- ArgStringList LlcArgs{
- InputFileName, "-mtriple=amdgcn-amd-amdhsa",
- Args.MakeArgString(Twine("-filetype=") + (OutputIsAsm ? "asm" : "obj")),
- Args.MakeArgString("-mcpu=" + SubArchName)};
+ 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")));
// Extract all the -m options
std::vector<llvm::StringRef> Features;
@@ -292,6 +307,20 @@ void HIPToolChain::addClangTargetOptions(
false))
CC1Args.push_back("-fgpu-rdc");
+ StringRef MaxThreadsPerBlock =
+ DriverArgs.getLastArgValue(options::OPT_gpu_max_threads_per_block_EQ);
+ if (!MaxThreadsPerBlock.empty()) {
+ std::string ArgStr =
+ std::string("--gpu-max-threads-per-block=") + MaxThreadsPerBlock.str();
+ CC1Args.push_back(DriverArgs.MakeArgStringRef(ArgStr));
+ }
+
+ if (DriverArgs.hasFlag(options::OPT_fgpu_allow_device_init,
+ options::OPT_fno_gpu_allow_device_init, false))
+ CC1Args.push_back("-fgpu-allow-device-init");
+
+ CC1Args.push_back("-fcuda-allow-variadic-functions");
+
// Default to "hidden" visibility, as object level linking will not be
// supported for the foreseeable future.
if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
@@ -337,9 +366,8 @@ void HIPToolChain::addClangTargetOptions(
else
WaveFrontSizeBC = "oclc_wavefrontsize64_off.amdgcn.bc";
- BCLibs.append({"hip.amdgcn.bc", "opencl.amdgcn.bc", "ocml.amdgcn.bc",
- "ockl.amdgcn.bc", "oclc_finite_only_off.amdgcn.bc",
- FlushDenormalControlBC,
+ 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});
diff --git a/clang/lib/Driver/ToolChains/HIP.h b/clang/lib/Driver/ToolChains/HIP.h
index 2d146ce5cc6fd..c4f944e458bf2 100644
--- a/clang/lib/Driver/ToolChains/HIP.h
+++ b/clang/lib/Driver/ToolChains/HIP.h
@@ -113,7 +113,7 @@ public:
computeMSVCVersion(const Driver *D,
const llvm::opt::ArgList &Args) const override;
- unsigned GetDefaultDwarfVersion() const override { return 2; }
+ unsigned GetDefaultDwarfVersion() const override { return 4; }
const ToolChain &HostTC;
diff --git a/clang/lib/Driver/ToolChains/Hexagon.cpp b/clang/lib/Driver/ToolChains/Hexagon.cpp
index 96cc084e2821e..e4d9ea8a70f9e 100644
--- a/clang/lib/Driver/ToolChains/Hexagon.cpp
+++ b/clang/lib/Driver/ToolChains/Hexagon.cpp
@@ -209,7 +209,11 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
bool IncStartFiles = !Args.hasArg(options::OPT_nostartfiles);
bool IncDefLibs = !Args.hasArg(options::OPT_nodefaultlibs);
bool UseG0 = false;
+ const char *Exec = Args.MakeArgString(HTC.GetLinkerPath());
+ bool UseLLD = (llvm::sys::path::filename(Exec).equals_lower("ld.lld") ||
+ llvm::sys::path::stem(Exec).equals_lower("ld.lld"));
bool UseShared = IsShared && !IsStatic;
+ StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args);
//----------------------------------------------------------------------------
// Silence warnings for various options
@@ -232,9 +236,10 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
for (const auto &Opt : HTC.ExtraOpts)
CmdArgs.push_back(Opt.c_str());
- CmdArgs.push_back("-march=hexagon");
- StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args);
- CmdArgs.push_back(Args.MakeArgString("-mcpu=hexagon" + CpuVer));
+ if (!UseLLD) {
+ CmdArgs.push_back("-march=hexagon");
+ CmdArgs.push_back(Args.MakeArgString("-mcpu=hexagon" + CpuVer));
+ }
if (IsShared) {
CmdArgs.push_back("-shared");
@@ -574,7 +579,7 @@ const StringRef HexagonToolChain::GetDefaultCPU() {
const StringRef HexagonToolChain::GetTargetCPUVersion(const ArgList &Args) {
Arg *CpuArg = nullptr;
- if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ, options::OPT_march_EQ))
+ if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
CpuArg = A;
StringRef CPU = CpuArg ? CpuArg->getValue() : GetDefaultCPU();
diff --git a/clang/lib/Driver/ToolChains/Hurd.cpp b/clang/lib/Driver/ToolChains/Hurd.cpp
index 92b0a7f2483f3..72166ca9f3594 100644
--- a/clang/lib/Driver/ToolChains/Hurd.cpp
+++ b/clang/lib/Driver/ToolChains/Hurd.cpp
@@ -27,9 +27,9 @@ using tools::addPathIfExists;
/// a target-triple directory in the library and header search paths.
/// Unfortunately, this triple does not align with the vanilla target triple,
/// so we provide a rough mapping here.
-static std::string getMultiarchTriple(const Driver &D,
- const llvm::Triple &TargetTriple,
- StringRef SysRoot) {
+std::string Hurd::getMultiarchTriple(const Driver &D,
+ const llvm::Triple &TargetTriple,
+ StringRef SysRoot) const {
if (TargetTriple.getArch() == llvm::Triple::x86) {
// We use the existence of '/lib/<triple>' as a directory to detect some
// common hurd triples that don't quite match the Clang triple for both
@@ -70,6 +70,10 @@ Hurd::Hurd(const Driver &D, const llvm::Triple &Triple,
const std::string OSLibDir = 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.
// FIXME: It's not clear whether we should use the driver's installed
diff --git a/clang/lib/Driver/ToolChains/Hurd.h b/clang/lib/Driver/ToolChains/Hurd.h
index a2c3d074e9f95..86c6c3f734dd9 100644
--- a/clang/lib/Driver/ToolChains/Hurd.h
+++ b/clang/lib/Driver/ToolChains/Hurd.h
@@ -36,6 +36,10 @@ public:
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
+
+ std::string getMultiarchTriple(const Driver &D,
+ const llvm::Triple &TargetTriple,
+ StringRef SysRoot) const override;
};
} // end namespace toolchains
diff --git a/clang/lib/Driver/ToolChains/InterfaceStubs.cpp b/clang/lib/Driver/ToolChains/InterfaceStubs.cpp
index 6677843b2c533..8f947e79bd1f1 100644
--- a/clang/lib/Driver/ToolChains/InterfaceStubs.cpp
+++ b/clang/lib/Driver/ToolChains/InterfaceStubs.cpp
@@ -9,6 +9,7 @@
#include "InterfaceStubs.h"
#include "CommonArgs.h"
#include "clang/Driver/Compilation.h"
+#include "llvm/Support/Path.h"
namespace clang {
namespace driver {
@@ -21,13 +22,38 @@ void Merger::ConstructJob(Compilation &C, const JobAction &JA,
std::string Merger = getToolChain().GetProgramPath(getShortName());
llvm::opt::ArgStringList CmdArgs;
CmdArgs.push_back("-action");
- CmdArgs.push_back(Args.getLastArg(options::OPT_emit_merged_ifs)
- ? "write-ifs"
- : "write-bin");
+ const bool WriteBin = !Args.getLastArg(options::OPT_emit_merged_ifs);
+ CmdArgs.push_back(WriteBin ? "write-bin" : "write-ifs");
CmdArgs.push_back("-o");
- CmdArgs.push_back(Output.getFilename());
- for (const auto &Input : Inputs)
- CmdArgs.push_back(Input.getFilename());
+
+ // Normally we want to write to a side-car file ending in ".ifso" so for
+ // example if `clang -emit-interface-stubs -shared -o libhello.so` were
+ // invoked then we would like to get libhello.so and libhello.ifso. If the
+ // stdout stream is given as the output file (ie `-o -`), that is the one
+ // exception where we will just append to the same filestream as the normal
+ // output.
+ SmallString<128> OutputFilename(Output.getFilename());
+ if (OutputFilename != "-") {
+ if (Args.hasArg(options::OPT_shared))
+ llvm::sys::path::replace_extension(OutputFilename,
+ (WriteBin ? "ifso" : "ifs"));
+ else
+ OutputFilename += (WriteBin ? ".ifso" : ".ifs");
+ }
+
+ CmdArgs.push_back(Args.MakeArgString(OutputFilename.c_str()));
+
+ // Here we append the input files. If the input files are object files, then
+ // we look for .ifs files present in the same location as the object files.
+ for (const auto &Input : Inputs) {
+ if (!Input.isFilename())
+ continue;
+ SmallString<128> InputFilename(Input.getFilename());
+ if (Input.getType() == types::TY_Object)
+ llvm::sys::path::replace_extension(InputFilename, ".ifs");
+ CmdArgs.push_back(Args.MakeArgString(InputFilename.c_str()));
+ }
+
C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Merger),
CmdArgs, Inputs));
}
diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
index 087783875ffe2..bff1ab1009be1 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -37,9 +37,9 @@ using tools::addPathIfExists;
/// a target-triple directory in the library and header search paths.
/// Unfortunately, this triple does not align with the vanilla target triple,
/// so we provide a rough mapping here.
-static std::string getMultiarchTriple(const Driver &D,
+std::string Linux::getMultiarchTriple(const Driver &D,
const llvm::Triple &TargetTriple,
- StringRef SysRoot) {
+ StringRef SysRoot) const {
llvm::Triple::EnvironmentType TargetEnvironment =
TargetTriple.getEnvironment();
bool IsAndroid = TargetTriple.isAndroid();
@@ -240,7 +240,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
.str());
}
- Distro Distro(D.getVFS());
+ Distro Distro(D.getVFS(), Triple);
if (Distro.IsAlpineLinux() || Triple.isAndroid()) {
ExtraOpts.push_back("-z");
@@ -511,7 +511,7 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
const llvm::Triple::ArchType Arch = getArch();
const llvm::Triple &Triple = getTriple();
- const Distro Distro(getDriver().getVFS());
+ const Distro Distro(getDriver().getVFS(), Triple);
if (Triple.isAndroid())
return Triple.isArch64Bit() ? "/system/bin/linker64" : "/system/bin/linker";
@@ -865,81 +865,23 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);
}
-static std::string DetectLibcxxIncludePath(llvm::vfs::FileSystem &vfs,
- StringRef base) {
- std::error_code EC;
- int MaxVersion = 0;
- std::string MaxVersionString = "";
- for (llvm::vfs::directory_iterator LI = vfs.dir_begin(base, EC), LE;
- !EC && LI != LE; LI = LI.increment(EC)) {
- StringRef VersionText = llvm::sys::path::filename(LI->path());
- int Version;
- if (VersionText[0] == 'v' &&
- !VersionText.slice(1, StringRef::npos).getAsInteger(10, Version)) {
- if (Version > MaxVersion) {
- MaxVersion = Version;
- MaxVersionString = VersionText;
- }
- }
- }
- return MaxVersion ? (base + "/" + MaxVersionString).str() : "";
-}
-
-void Linux::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const {
- const std::string& SysRoot = computeSysRoot();
- const std::string LibCXXIncludePathCandidates[] = {
- DetectLibcxxIncludePath(getVFS(), getDriver().Dir + "/../include/c++"),
- // 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:
- DetectLibcxxIncludePath(getVFS(), SysRoot + "/usr/local/include/c++"),
- DetectLibcxxIncludePath(getVFS(), SysRoot + "/usr/include/c++") };
- for (const auto &IncludePath : LibCXXIncludePathCandidates) {
- if (IncludePath.empty() || !getVFS().exists(IncludePath))
- continue;
- // Use the first candidate that exists.
- addSystemInclude(DriverArgs, CC1Args, IncludePath);
- return;
- }
-}
-
void Linux::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
+ // Try generic GCC detection first.
+ if (Generic_GCC::addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args))
+ return;
+
// We need a detected GCC installation on Linux to provide libstdc++'s
- // headers.
+ // headers in odd Linuxish places.
if (!GCCInstallation.isValid())
return;
- // By default, look for the C++ headers in an include directory adjacent to
- // the lib directory of the GCC installation. Note that this is expect to be
- // equivalent to '/usr/include/c++/X.Y' in almost all cases.
StringRef LibDir = GCCInstallation.getParentLibPath();
- StringRef InstallDir = GCCInstallation.getInstallPath();
StringRef TripleStr = GCCInstallation.getTriple().str();
const Multilib &Multilib = GCCInstallation.getMultilib();
- const std::string GCCMultiarchTriple = getMultiarchTriple(
- getDriver(), GCCInstallation.getTriple(), getDriver().SysRoot);
- const std::string TargetMultiarchTriple =
- getMultiarchTriple(getDriver(), getTriple(), getDriver().SysRoot);
const GCCVersion &Version = GCCInstallation.getVersion();
- // The primary search for libstdc++ supports multiarch variants.
- if (addLibStdCXXIncludePaths(LibDir.str() + "/../include",
- "/c++/" + Version.Text, TripleStr,
- GCCMultiarchTriple, TargetMultiarchTriple,
- Multilib.includeSuffix(), DriverArgs, CC1Args))
- return;
-
- // Otherwise, fall back on a bunch of options which don't use multiarch
- // layouts for simplicity.
const std::string LibStdCXXIncludePathCandidates[] = {
- // Gentoo is weird and places its headers inside the GCC install,
- // so if the first attempt to find the headers fails, try these patterns.
- InstallDir.str() + "/include/g++-v" + Version.Text,
- InstallDir.str() + "/include/g++-v" + Version.MajorStr + "." +
- Version.MinorStr,
- InstallDir.str() + "/include/g++-v" + Version.MajorStr,
// Android standalone toolchain has C++ headers in yet another place.
LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text,
// Freescale SDK C++ headers are directly in <sysroot>/usr/include/c++,
diff --git a/clang/lib/Driver/ToolChains/Linux.h b/clang/lib/Driver/ToolChains/Linux.h
index 4c61994691c73..f5518eac218a4 100644
--- a/clang/lib/Driver/ToolChains/Linux.h
+++ b/clang/lib/Driver/ToolChains/Linux.h
@@ -26,9 +26,6 @@ public:
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- void addLibCxxIncludePaths(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
void addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
@@ -52,6 +49,10 @@ public:
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
+
+ std::string getMultiarchTriple(const Driver &D,
+ const llvm::Triple &TargetTriple,
+ StringRef SysRoot) const override;
};
} // end namespace toolchains
diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp
index 1d31844bfcc88..4e143f6a5d3fa 100644
--- a/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -422,6 +422,17 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link);
+ // Control Flow Guard checks
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) {
+ StringRef GuardArgs = A->getValue();
+ if (GuardArgs.equals_lower("cf") || GuardArgs.equals_lower("cf,nochecks")) {
+ // MSVC doesn't yet support the "nochecks" modifier.
+ CmdArgs.push_back("-guard:cf");
+ } else if (GuardArgs.equals_lower("cf-")) {
+ CmdArgs.push_back("-guard:cf-");
+ }
+ }
+
if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
options::OPT_fno_openmp, false)) {
CmdArgs.push_back("-nodefaultlib:vcomp.lib");
@@ -679,6 +690,17 @@ std::unique_ptr<Command> visualstudio::Compiler::GetCommand(
: "/Zc:threadSafeInit-");
}
+ // Control Flow Guard checks
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) {
+ StringRef GuardArgs = A->getValue();
+ if (GuardArgs.equals_lower("cf") || GuardArgs.equals_lower("cf,nochecks")) {
+ // MSVC doesn't yet support the "nochecks" modifier.
+ CmdArgs.push_back("/guard:cf");
+ } else if (GuardArgs.equals_lower("cf-")) {
+ CmdArgs.push_back("/guard:cf-");
+ }
+ }
+
// Pass through all unknown arguments so that the fallback command can see
// them too.
Args.AddAllArgs(CmdArgs, options::OPT_UNKNOWN);
diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp
index 0d851114c225b..8f24384e688b4 100644
--- a/clang/lib/Driver/ToolChains/MinGW.cpp
+++ b/clang/lib/Driver/ToolChains/MinGW.cpp
@@ -160,7 +160,19 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
CmdArgs.push_back("-o");
- CmdArgs.push_back(Output.getFilename());
+ const char *OutputFile = Output.getFilename();
+ // GCC implicitly adds an .exe extension if it is given an output file name
+ // that lacks an extension. However, GCC only does this when actually
+ // running on windows, not when operating as a cross compiler. As some users
+ // have come to rely on this behaviour, try to replicate it.
+#ifdef _WIN32
+ if (!llvm::sys::path::has_extension(OutputFile))
+ CmdArgs.push_back(Args.MakeArgString(Twine(OutputFile) + ".exe"));
+ else
+ CmdArgs.push_back(OutputFile);
+#else
+ CmdArgs.push_back(OutputFile);
+#endif
Args.AddAllArgs(CmdArgs, options::OPT_e);
// FIXME: add -N, -n flags
diff --git a/clang/lib/Driver/ToolChains/NetBSD.cpp b/clang/lib/Driver/ToolChains/NetBSD.cpp
index 405142204199d..0100a387d6c35 100644
--- a/clang/lib/Driver/ToolChains/NetBSD.cpp
+++ b/clang/lib/Driver/ToolChains/NetBSD.cpp
@@ -505,7 +505,7 @@ void NetBSD::addClangTargetOptions(const ArgList &DriverArgs,
getTriple().getArch() == llvm::Triple::arm ||
getTriple().getArch() == llvm::Triple::armeb;
- if (DriverArgs.hasFlag(options::OPT_fuse_init_array,
- options::OPT_fno_use_init_array, UseInitArrayDefault))
- CC1Args.push_back("-fuse-init-array");
+ if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
+ options::OPT_fno_use_init_array, UseInitArrayDefault))
+ CC1Args.push_back("-fno-use-init-array");
}
diff --git a/clang/lib/Driver/ToolChains/OpenBSD.cpp b/clang/lib/Driver/ToolChains/OpenBSD.cpp
index e93f5fcc3d819..80343c0394cb5 100644
--- a/clang/lib/Driver/ToolChains/OpenBSD.cpp
+++ b/clang/lib/Driver/ToolChains/OpenBSD.cpp
@@ -267,3 +267,12 @@ Tool *OpenBSD::buildAssembler() const {
}
Tool *OpenBSD::buildLinker() const { return new tools::openbsd::Linker(*this); }
+
+void OpenBSD::addClangTargetOptions(const ArgList &DriverArgs,
+ ArgStringList &CC1Args,
+ Action::OffloadKind) const {
+ // Support for .init_array is still new (Aug 2016).
+ if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
+ options::OPT_fno_use_init_array, false))
+ CC1Args.push_back("-fno-use-init-array");
+}
diff --git a/clang/lib/Driver/ToolChains/OpenBSD.h b/clang/lib/Driver/ToolChains/OpenBSD.h
index c92d109b7c16c..9f1ee0f66402b 100644
--- a/clang/lib/Driver/ToolChains/OpenBSD.h
+++ b/clang/lib/Driver/ToolChains/OpenBSD.h
@@ -75,6 +75,11 @@ public:
SanitizerMask getSupportedSanitizers() const override;
+ void
+ addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadKind) const override;
+
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
diff --git a/clang/lib/Driver/ToolChains/PS4CPU.h b/clang/lib/Driver/ToolChains/PS4CPU.h
index e9f0891c11944..18852b2808cbd 100644
--- a/clang/lib/Driver/ToolChains/PS4CPU.h
+++ b/clang/lib/Driver/ToolChains/PS4CPU.h
@@ -84,6 +84,10 @@ public:
SanitizerMask getSupportedSanitizers() const override;
+ // PS4 toolchain uses legacy thin LTO API, which is not
+ // capable of unit splitting.
+ bool canSplitThinLTOUnit() const override { return false; }
+
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 22dc5117f1962..ddc329e3c722b 100644
--- a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
+++ b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
@@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
#include "RISCVToolchain.h"
-#include "Arch/RISCV.h"
#include "CommonArgs.h"
#include "InputInfo.h"
#include "clang/Driver/Compilation.h"
@@ -23,29 +22,60 @@ using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;
+static void addMultilibsFilePaths(const Driver &D, const MultilibSet &Multilibs,
+ const Multilib &Multilib,
+ StringRef InstallPath,
+ ToolChain::path_list &Paths) {
+ if (const auto &PathsCallback = Multilibs.filePathsCallback())
+ for (const auto &Path : PathsCallback(Multilib))
+ addPathIfExists(D, InstallPath + Path, Paths);
+}
+
/// RISCV Toolchain
RISCVToolChain::RISCVToolChain(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
GCCInstallation.init(Triple, Args);
- getFilePaths().push_back(computeSysRoot() + "/lib");
if (GCCInstallation.isValid()) {
+ Multilibs = GCCInstallation.getMultilibs();
+ SelectedMultilib = GCCInstallation.getMultilib();
+ path_list &Paths = getFilePaths();
+ // Add toolchain/multilib specific file paths.
+ addMultilibsFilePaths(D, Multilibs, SelectedMultilib,
+ GCCInstallation.getInstallPath(), Paths);
getFilePaths().push_back(GCCInstallation.getInstallPath().str());
- getProgramPaths().push_back(
- (GCCInstallation.getParentLibPath() + "/../bin").str());
+ ToolChain::path_list &PPaths = getProgramPaths();
+ // Multilib cross-compiler GCC installations put ld in a triple-prefixed
+ // directory off of the parent of the GCC installation.
+ PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +
+ GCCInstallation.getTriple().str() + "/bin")
+ .str());
+ PPaths.push_back((GCCInstallation.getParentLibPath() + "/../bin").str());
+ } else {
+ getProgramPaths().push_back(D.Dir);
}
+ getFilePaths().push_back(computeSysRoot() + "/lib");
}
Tool *RISCVToolChain::buildLinker() const {
return new tools::RISCV::Linker(*this);
}
+ToolChain::RuntimeLibType RISCVToolChain::GetDefaultRuntimeLibType() const {
+ return GCCInstallation.isValid() ?
+ ToolChain::RLT_Libgcc : ToolChain::RLT_CompilerRT;
+}
+
+ToolChain::UnwindLibType
+RISCVToolChain::GetUnwindLibType(const llvm::opt::ArgList &Args) const {
+ return ToolChain::UNW_None;
+}
+
void RISCVToolChain::addClangTargetOptions(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind) const {
CC1Args.push_back("-nostdsysteminc");
- CC1Args.push_back("-fuse-init-array");
}
void RISCVToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
@@ -74,17 +104,22 @@ std::string RISCVToolChain::computeSysRoot() const {
if (!getDriver().SysRoot.empty())
return getDriver().SysRoot;
- if (!GCCInstallation.isValid())
- return std::string();
-
- StringRef LibDir = GCCInstallation.getParentLibPath();
- StringRef TripleStr = GCCInstallation.getTriple().str();
- std::string SysRootDir = LibDir.str() + "/../" + TripleStr.str();
+ SmallString<128> SysRootDir;
+ if (GCCInstallation.isValid()) {
+ StringRef LibDir = GCCInstallation.getParentLibPath();
+ StringRef TripleStr = GCCInstallation.getTriple().str();
+ llvm::sys::path::append(SysRootDir, LibDir, "..", TripleStr);
+ } else {
+ // Use the triple as provided to the driver. Unlike the parsed triple
+ // this has not been normalized to always contain every field.
+ llvm::sys::path::append(SysRootDir, getDriver().Dir, "..",
+ getDriver().getTargetTriple());
+ }
if (!llvm::sys::fs::exists(SysRootDir))
return std::string();
- return SysRootDir;
+ return SysRootDir.str();
}
void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -99,20 +134,35 @@ void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (!D.SysRoot.empty())
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
- std::string Linker = getToolChain().GetProgramPath(getShortName());
-
- if (D.isUsingLTO()) {
- assert(!Inputs.empty() && "Must have at least one input.");
- AddGoldPlugin(ToolChain, Args, CmdArgs, Output, Inputs[0],
- D.getLTOMode() == LTOK_Thin);
+ bool IsRV64 = ToolChain.getArch() == llvm::Triple::riscv64;
+ CmdArgs.push_back("-m");
+ if (IsRV64) {
+ CmdArgs.push_back("elf64lriscv");
+ } else {
+ CmdArgs.push_back("elf32lriscv");
}
+ std::string Linker = getToolChain().GetProgramPath(getShortName());
+
bool WantCRTs =
!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles);
+ const char *crtbegin, *crtend;
+ auto RuntimeLib = ToolChain.GetRuntimeLibType(Args);
+ if (RuntimeLib == ToolChain::RLT_Libgcc) {
+ crtbegin = "crtbegin.o";
+ crtend = "crtend.o";
+ } else {
+ assert (RuntimeLib == ToolChain::RLT_CompilerRT);
+ crtbegin = ToolChain.getCompilerRTArgString(Args, "crtbegin",
+ ToolChain::FT_Object);
+ crtend = ToolChain.getCompilerRTArgString(Args, "crtend",
+ ToolChain::FT_Object);
+ }
+
if (WantCRTs) {
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
}
Args.AddAllArgs(CmdArgs, options::OPT_L);
@@ -133,11 +183,11 @@ void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lc");
CmdArgs.push_back("-lgloss");
CmdArgs.push_back("--end-group");
- CmdArgs.push_back("-lgcc");
+ AddRunTimeLibs(ToolChain, ToolChain.getDriver(), CmdArgs, Args);
}
if (WantCRTs)
- CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
diff --git a/clang/lib/Driver/ToolChains/RISCVToolchain.h b/clang/lib/Driver/ToolChains/RISCVToolchain.h
index 673d749d76ff7..bb7f64849bcb6 100644
--- a/clang/lib/Driver/ToolChains/RISCVToolchain.h
+++ b/clang/lib/Driver/ToolChains/RISCVToolchain.h
@@ -25,7 +25,9 @@ public:
void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind) const override;
- bool HasNativeLLVMSupport() const override { return true; }
+ RuntimeLibType GetDefaultRuntimeLibType() const override;
+ UnwindLibType
+ GetUnwindLibType(const llvm::opt::ArgList &Args) const override;
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp
index 3add913b700fa..907f86b8233c5 100644
--- a/clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -8,6 +8,7 @@
#include "WebAssembly.h"
#include "CommonArgs.h"
+#include "clang/Basic/Version.h"
#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
@@ -90,6 +91,39 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Output.getFilename());
C.addCommand(std::make_unique<Command>(JA, *this, Linker, CmdArgs, Inputs));
+
+ // When optimizing, if wasm-opt is available, run it.
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
+ auto WasmOptPath = getToolChain().GetProgramPath("wasm-opt");
+ if (WasmOptPath != "wasm-opt") {
+ StringRef OOpt = "s";
+ if (A->getOption().matches(options::OPT_O4) ||
+ A->getOption().matches(options::OPT_Ofast))
+ OOpt = "4";
+ else if (A->getOption().matches(options::OPT_O0))
+ OOpt = "0";
+ else if (A->getOption().matches(options::OPT_O))
+ OOpt = A->getValue();
+
+ if (OOpt != "0") {
+ const char *WasmOpt = Args.MakeArgString(WasmOptPath);
+ ArgStringList CmdArgs;
+ CmdArgs.push_back(Output.getFilename());
+ CmdArgs.push_back(Args.MakeArgString(llvm::Twine("-O") + OOpt));
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ C.addCommand(std::make_unique<Command>(JA, *this, WasmOpt, CmdArgs, Inputs));
+ }
+ }
+ }
+}
+
+/// Given a base library directory, append path components to form the
+/// LTO directory.
+static std::string AppendLTOLibDir(const std::string &Dir) {
+ // The version allows the path to be keyed to the specific version of
+ // LLVM in used, as the bitcode format is not stable.
+ return Dir + "/llvm-lto/" LLVM_VERSION_STRING;
}
WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple,
@@ -100,16 +134,24 @@ WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple,
getProgramPaths().push_back(getDriver().getInstalledDir());
+ auto SysRoot = getDriver().SysRoot;
if (getTriple().getOS() == llvm::Triple::UnknownOS) {
// Theoretically an "unknown" OS should mean no standard libraries, however
// it could also mean that a custom set of libraries is in use, so just add
// /lib to the search path. Disable multiarch in this case, to discourage
// paths containing "unknown" from acquiring meanings.
- getFilePaths().push_back(getDriver().SysRoot + "/lib");
+ getFilePaths().push_back(SysRoot + "/lib");
} else {
const std::string MultiarchTriple =
- getMultiarchTriple(getDriver(), Triple, getDriver().SysRoot);
- getFilePaths().push_back(getDriver().SysRoot + "/lib/" + MultiarchTriple);
+ getMultiarchTriple(getDriver(), Triple, SysRoot);
+ if (D.isUsingLTO()) {
+ // For LTO, enable use of lto-enabled sysroot libraries too, if available.
+ // Note that the directory is keyed to the LLVM revision, as LLVM's
+ // bitcode format is not stable.
+ auto Dir = AppendLTOLibDir(SysRoot + "/lib/" + MultiarchTriple);
+ getFilePaths().push_back(Dir);
+ }
+ getFilePaths().push_back(SysRoot + "/lib/" + MultiarchTriple);
}
}
@@ -137,9 +179,9 @@ bool WebAssembly::HasNativeLLVMSupport() const { return true; }
void WebAssembly::addClangTargetOptions(const ArgList &DriverArgs,
ArgStringList &CC1Args,
Action::OffloadKind) const {
- if (DriverArgs.hasFlag(clang::driver::options::OPT_fuse_init_array,
- options::OPT_fno_use_init_array, true))
- CC1Args.push_back("-fuse-init-array");
+ if (!DriverArgs.hasFlag(clang::driver::options::OPT_fuse_init_array,
+ options::OPT_fno_use_init_array, true))
+ CC1Args.push_back("-fno-use-init-array");
// '-pthread' implies atomics, bulk-memory, mutable-globals, and sign-ext
if (DriverArgs.hasFlag(options::OPT_pthread, options::OPT_no_pthread,
@@ -181,6 +223,12 @@ void WebAssembly::addClangTargetOptions(const ArgList &DriverArgs,
getDriver().Diag(diag::err_drv_argument_not_allowed_with)
<< "-fwasm-exceptions"
<< "-mno-exception-handling";
+ // '-fwasm-exceptions' is not compatible with '-mno-reference-types'
+ if (DriverArgs.hasFlag(options::OPT_mno_reference_types,
+ options::OPT_mexception_handing, false))
+ getDriver().Diag(diag::err_drv_argument_not_allowed_with)
+ << "-fwasm-exceptions"
+ << "-mno-reference-types";
// '-fwasm-exceptions' is not compatible with
// '-mllvm -enable-emscripten-cxx-exceptions'
for (const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
@@ -189,9 +237,11 @@ void WebAssembly::addClangTargetOptions(const ArgList &DriverArgs,
<< "-fwasm-exceptions"
<< "-mllvm -enable-emscripten-cxx-exceptions";
}
- // '-fwasm-exceptions' implies exception-handling
+ // '-fwasm-exceptions' implies exception-handling and reference-types
CC1Args.push_back("-target-feature");
CC1Args.push_back("+exception-handling");
+ CC1Args.push_back("-target-feature");
+ CC1Args.push_back("+reference-types");
}
}
diff --git a/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp
index a30710645af3a..7d83be2521e73 100644
--- a/clang/lib/Driver/Types.cpp
+++ b/clang/lib/Driver/Types.cpp
@@ -212,6 +212,16 @@ bool types::isHIP(ID Id) {
}
}
+bool types::isFortran(ID Id) {
+ switch (Id) {
+ default:
+ return false;
+
+ case TY_Fortran: case TY_PP_Fortran:
+ return true;
+ }
+}
+
bool types::isSrcFile(ID Id) {
return Id != TY_Object && getPreprocessedType(Id) != TY_INVALID;
}
@@ -320,22 +330,6 @@ void types::getCompilationPhases(const clang::driver::Driver &Driver,
llvm::copy_if(PhaseList, std::back_inserter(P),
[](phases::ID Phase) { return Phase <= phases::Precompile; });
- // Treat Interface Stubs like its own compilation mode.
- else if (DAL.getLastArg(options::OPT_emit_interface_stubs)) {
- llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> IfsModePhaseList;
- llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> &PL = PhaseList;
- phases::ID LastPhase = phases::IfsMerge;
- if (Id != types::TY_IFS) {
- if (DAL.hasArg(options::OPT_c))
- LastPhase = phases::Compile;
- PL = IfsModePhaseList;
- types::getCompilationPhases(types::TY_IFS_CPP, PL);
- }
- llvm::copy_if(PL, std::back_inserter(P), [&](phases::ID Phase) {
- return Phase <= LastPhase;
- });
- }
-
// -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
else if (DAL.getLastArg(options::OPT_fsyntax_only) ||
DAL.getLastArg(options::OPT_print_supported_cpus) ||
diff --git a/clang/lib/Driver/XRayArgs.cpp b/clang/lib/Driver/XRayArgs.cpp
index 16e7c7ecf36b4..a2dd63f9eb77c 100644
--- a/clang/lib/Driver/XRayArgs.cpp
+++ b/clang/lib/Driver/XRayArgs.cpp
@@ -70,6 +70,13 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
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_,
@@ -129,7 +136,7 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
// are treated as actual dependencies.
for (const auto &Filename :
Args.getAllArgValues(options::OPT_fxray_always_instrument)) {
- if (llvm::sys::fs::exists(Filename)) {
+ if (D.getVFS().exists(Filename)) {
AlwaysInstrumentFiles.push_back(Filename);
ExtraDeps.push_back(Filename);
} else
@@ -138,7 +145,7 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
for (const auto &Filename :
Args.getAllArgValues(options::OPT_fxray_never_instrument)) {
- if (llvm::sys::fs::exists(Filename)) {
+ if (D.getVFS().exists(Filename)) {
NeverInstrumentFiles.push_back(Filename);
ExtraDeps.push_back(Filename);
} else
@@ -147,7 +154,7 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
for (const auto &Filename :
Args.getAllArgValues(options::OPT_fxray_attr_list)) {
- if (llvm::sys::fs::exists(Filename)) {
+ if (D.getVFS().exists(Filename)) {
AttrListFiles.push_back(Filename);
ExtraDeps.push_back(Filename);
} else