aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Driver
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:04:05 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:04:05 +0000
commit676fbe8105eeb6ff4bb2ed261cb212fcfdbe7b63 (patch)
tree02a1ac369cb734d0abfa5000dd86e5b7797e6a74 /lib/Driver
parentc7e70c433efc6953dc3888b9fbf9f3512d7da2b0 (diff)
downloadsrc-676fbe8105eeb6ff4bb2ed261cb212fcfdbe7b63.tar.gz
src-676fbe8105eeb6ff4bb2ed261cb212fcfdbe7b63.zip
Vendor import of clang trunk r351319 (just before the release_80 branchvendor/clang/clang-trunk-r351319
Notes
Notes: svn path=/vendor/clang/dist/; revision=343173 svn path=/vendor/clang/clang-trunk-r351319/; revision=343174; tag=vendor/clang/clang-trunk-r351319
Diffstat (limited to 'lib/Driver')
-rw-r--r--lib/Driver/Action.cpp16
-rw-r--r--lib/Driver/CMakeLists.txt5
-rw-r--r--lib/Driver/Compilation.cpp2
-rw-r--r--lib/Driver/DarwinSDKInfo.cpp44
-rw-r--r--lib/Driver/Distro.cpp9
-rw-r--r--lib/Driver/Driver.cpp478
-rw-r--r--lib/Driver/Job.cpp19
-rw-r--r--lib/Driver/SanitizerArgs.cpp51
-rw-r--r--lib/Driver/ToolChain.cpp49
-rw-r--r--lib/Driver/ToolChains/AMDGPU.cpp13
-rw-r--r--lib/Driver/ToolChains/AMDGPU.h4
-rw-r--r--lib/Driver/ToolChains/Arch/AArch64.cpp185
-rw-r--r--lib/Driver/ToolChains/Arch/AArch64.h5
-rw-r--r--lib/Driver/ToolChains/Arch/ARM.cpp58
-rw-r--r--lib/Driver/ToolChains/Arch/ARM.h2
-rw-r--r--lib/Driver/ToolChains/Arch/Mips.cpp12
-rw-r--r--lib/Driver/ToolChains/Arch/PPC.cpp10
-rw-r--r--lib/Driver/ToolChains/Arch/PPC.h2
-rw-r--r--lib/Driver/ToolChains/Arch/X86.cpp34
-rw-r--r--lib/Driver/ToolChains/BareMetal.cpp9
-rw-r--r--lib/Driver/ToolChains/Clang.cpp889
-rw-r--r--lib/Driver/ToolChains/CommonArgs.cpp200
-rw-r--r--lib/Driver/ToolChains/CommonArgs.h6
-rw-r--r--lib/Driver/ToolChains/CrossWindows.cpp1
-rw-r--r--lib/Driver/ToolChains/Cuda.cpp122
-rw-r--r--lib/Driver/ToolChains/Cuda.h2
-rw-r--r--lib/Driver/ToolChains/Darwin.cpp322
-rw-r--r--lib/Driver/ToolChains/Darwin.h21
-rw-r--r--lib/Driver/ToolChains/FreeBSD.cpp2
-rw-r--r--lib/Driver/ToolChains/Fuchsia.cpp22
-rw-r--r--lib/Driver/ToolChains/Gnu.cpp199
-rw-r--r--lib/Driver/ToolChains/HIP.cpp59
-rw-r--r--lib/Driver/ToolChains/HIP.h5
-rw-r--r--lib/Driver/ToolChains/Hexagon.cpp17
-rw-r--r--lib/Driver/ToolChains/Hexagon.h3
-rw-r--r--lib/Driver/ToolChains/Hurd.cpp169
-rw-r--r--lib/Driver/ToolChains/Hurd.h46
-rw-r--r--lib/Driver/ToolChains/Linux.cpp147
-rw-r--r--lib/Driver/ToolChains/Linux.h2
-rw-r--r--lib/Driver/ToolChains/MSP430.cpp233
-rw-r--r--lib/Driver/ToolChains/MSP430.h71
-rw-r--r--lib/Driver/ToolChains/MSVC.cpp35
-rw-r--r--lib/Driver/ToolChains/MSVC.h13
-rw-r--r--lib/Driver/ToolChains/MinGW.cpp66
-rw-r--r--lib/Driver/ToolChains/MinGW.h6
-rw-r--r--lib/Driver/ToolChains/Minix.cpp4
-rw-r--r--lib/Driver/ToolChains/MipsLinux.h2
-rw-r--r--lib/Driver/ToolChains/NetBSD.cpp14
-rw-r--r--lib/Driver/ToolChains/NetBSD.h4
-rw-r--r--lib/Driver/ToolChains/OpenBSD.cpp66
-rw-r--r--lib/Driver/ToolChains/OpenBSD.h8
-rw-r--r--lib/Driver/ToolChains/PS4CPU.cpp6
-rw-r--r--lib/Driver/ToolChains/RISCVToolchain.cpp (renamed from lib/Driver/ToolChains/RISCV.cpp)38
-rw-r--r--lib/Driver/ToolChains/RISCVToolchain.h (renamed from lib/Driver/ToolChains/RISCV.h)14
-rw-r--r--lib/Driver/ToolChains/Solaris.h2
-rw-r--r--lib/Driver/ToolChains/WebAssembly.cpp55
-rw-r--r--lib/Driver/ToolChains/WebAssembly.h17
-rw-r--r--lib/Driver/Types.cpp2
-rw-r--r--lib/Driver/XRayArgs.cpp33
59 files changed, 3092 insertions, 838 deletions
diff --git a/lib/Driver/Action.cpp b/lib/Driver/Action.cpp
index 99d588d9c009..d4c7040a233c 100644
--- a/lib/Driver/Action.cpp
+++ b/lib/Driver/Action.cpp
@@ -26,6 +26,7 @@ const char *Action::getClassName(ActionClass AC) {
return "offload";
case PreprocessJobClass: return "preprocessor";
case PrecompileJobClass: return "precompiler";
+ case HeaderModulePrecompileJobClass: return "header-module-precompiler";
case AnalyzeJobClass: return "analyzer";
case MigrateJobClass: return "migrator";
case CompileJobClass: return "compiler";
@@ -319,6 +320,19 @@ void PrecompileJobAction::anchor() {}
PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType)
: JobAction(PrecompileJobClass, Input, OutputType) {}
+PrecompileJobAction::PrecompileJobAction(ActionClass Kind, Action *Input,
+ types::ID OutputType)
+ : JobAction(Kind, Input, OutputType) {
+ assert(isa<PrecompileJobAction>((Action*)this) && "invalid action kind");
+}
+
+void HeaderModulePrecompileJobAction::anchor() {}
+
+HeaderModulePrecompileJobAction::HeaderModulePrecompileJobAction(
+ Action *Input, types::ID OutputType, const char *ModuleName)
+ : PrecompileJobAction(HeaderModulePrecompileJobClass, Input, OutputType),
+ ModuleName(ModuleName) {}
+
void AnalyzeJobAction::anchor() {}
AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType)
@@ -382,7 +396,7 @@ VerifyPCHJobAction::VerifyPCHJobAction(Action *Input, types::ID Type)
void OffloadBundlingJobAction::anchor() {}
OffloadBundlingJobAction::OffloadBundlingJobAction(ActionList &Inputs)
- : JobAction(OffloadBundlingJobClass, Inputs, Inputs.front()->getType()) {}
+ : JobAction(OffloadBundlingJobClass, Inputs, Inputs.back()->getType()) {}
void OffloadUnbundlingJobAction::anchor() {}
diff --git a/lib/Driver/CMakeLists.txt b/lib/Driver/CMakeLists.txt
index 2b03c9f7001f..4793a1f90b2f 100644
--- a/lib/Driver/CMakeLists.txt
+++ b/lib/Driver/CMakeLists.txt
@@ -12,6 +12,7 @@ endif()
add_clang_library(clangDriver
Action.cpp
Compilation.cpp
+ DarwinSDKInfo.cpp
Distro.cpp
Driver.cpp
DriverOptions.cpp
@@ -47,17 +48,19 @@ add_clang_library(clangDriver
ToolChains/Haiku.cpp
ToolChains/HIP.cpp
ToolChains/Hexagon.cpp
+ ToolChains/Hurd.cpp
ToolChains/Linux.cpp
ToolChains/MipsLinux.cpp
ToolChains/MinGW.cpp
ToolChains/Minix.cpp
+ ToolChains/MSP430.cpp
ToolChains/MSVC.cpp
ToolChains/Myriad.cpp
ToolChains/NaCl.cpp
ToolChains/NetBSD.cpp
ToolChains/OpenBSD.cpp
ToolChains/PS4CPU.cpp
- ToolChains/RISCV.cpp
+ ToolChains/RISCVToolchain.cpp
ToolChains/Solaris.cpp
ToolChains/TCE.cpp
ToolChains/WebAssembly.cpp
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
index ca2525dd07fb..982d7ecad962 100644
--- a/lib/Driver/Compilation.cpp
+++ b/lib/Driver/Compilation.cpp
@@ -127,7 +127,7 @@ bool Compilation::CleanupFile(const char *File, bool IssueErrors) const {
return true;
}
-bool Compilation::CleanupFileList(const ArgStringList &Files,
+bool Compilation::CleanupFileList(const llvm::opt::ArgStringList &Files,
bool IssueErrors) const {
bool Success = true;
for (const auto &File: Files)
diff --git a/lib/Driver/DarwinSDKInfo.cpp b/lib/Driver/DarwinSDKInfo.cpp
new file mode 100644
index 000000000000..547978b2f973
--- /dev/null
+++ b/lib/Driver/DarwinSDKInfo.cpp
@@ -0,0 +1,44 @@
+//===--- DarwinSDKInfo.cpp - SDK Information parser for darwin - ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/DarwinSDKInfo.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+
+using namespace clang::driver;
+using namespace clang;
+
+Expected<Optional<DarwinSDKInfo>>
+driver::parseDarwinSDKInfo(llvm::vfs::FileSystem &VFS, StringRef SDKRootPath) {
+ llvm::SmallString<256> Filepath = SDKRootPath;
+ llvm::sys::path::append(Filepath, "SDKSettings.json");
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
+ VFS.getBufferForFile(Filepath);
+ if (!File) {
+ // If the file couldn't be read, assume it just doesn't exist.
+ return None;
+ }
+ Expected<llvm::json::Value> Result =
+ llvm::json::parse(File.get()->getBuffer());
+ if (!Result)
+ return Result.takeError();
+
+ if (const auto *Obj = Result->getAsObject()) {
+ auto VersionString = Obj->getString("Version");
+ if (VersionString) {
+ VersionTuple Version;
+ if (!Version.tryParse(*VersionString))
+ return DarwinSDKInfo(Version);
+ }
+ }
+ return llvm::make_error<llvm::StringError>("invalid SDKSettings.json",
+ llvm::inconvertibleErrorCode());
+}
diff --git a/lib/Driver/Distro.cpp b/lib/Driver/Distro.cpp
index 2c4d44faf8d0..396d0bee5603 100644
--- a/lib/Driver/Distro.cpp
+++ b/lib/Driver/Distro.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Driver/Distro.h"
+#include "clang/Basic/LLVM.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
@@ -17,7 +18,7 @@
using namespace clang::driver;
using namespace clang;
-static Distro::DistroType DetectDistro(vfs::FileSystem &VFS) {
+static Distro::DistroType DetectDistro(llvm::vfs::FileSystem &VFS) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
VFS.getBufferForFile("/etc/lsb-release");
if (File) {
@@ -50,6 +51,7 @@ static Distro::DistroType DetectDistro(vfs::FileSystem &VFS) {
.Case("artful", Distro::UbuntuArtful)
.Case("bionic", Distro::UbuntuBionic)
.Case("cosmic", Distro::UbuntuCosmic)
+ .Case("disco", Distro::UbuntuDisco)
.Default(Distro::UnknownDistro);
if (Version != Distro::UnknownDistro)
return Version;
@@ -136,7 +138,10 @@ static Distro::DistroType DetectDistro(vfs::FileSystem &VFS) {
if (VFS.exists("/etc/arch-release"))
return Distro::ArchLinux;
+ if (VFS.exists("/etc/gentoo-release"))
+ return Distro::Gentoo;
+
return Distro::UnknownDistro;
}
-Distro::Distro(vfs::FileSystem &VFS) : DistroVal(DetectDistro(VFS)) {}
+Distro::Distro(llvm::vfs::FileSystem &VFS) : DistroVal(DetectDistro(VFS)) {}
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 952a716cb6e6..a784e218f139 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -26,8 +26,10 @@
#include "ToolChains/HIP.h"
#include "ToolChains/Haiku.h"
#include "ToolChains/Hexagon.h"
+#include "ToolChains/Hurd.h"
#include "ToolChains/Lanai.h"
#include "ToolChains/Linux.h"
+#include "ToolChains/MSP430.h"
#include "ToolChains/MSVC.h"
#include "ToolChains/MinGW.h"
#include "ToolChains/Minix.h"
@@ -37,13 +39,12 @@
#include "ToolChains/NetBSD.h"
#include "ToolChains/OpenBSD.h"
#include "ToolChains/PS4CPU.h"
-#include "ToolChains/RISCV.h"
+#include "ToolChains/RISCVToolchain.h"
#include "ToolChains/Solaris.h"
#include "ToolChains/TCE.h"
#include "ToolChains/WebAssembly.h"
#include "ToolChains/XCore.h"
#include "clang/Basic/Version.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Config/config.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Compilation.h"
@@ -68,18 +69,21 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/StringSaver.h"
#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <map>
#include <memory>
#include <utility>
#if LLVM_ON_UNIX
#include <unistd.h> // getpid
+#include <sysexits.h> // EX_IOERR
#endif
using namespace clang::driver;
@@ -88,7 +92,7 @@ using namespace llvm::opt;
Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple,
DiagnosticsEngine &Diags,
- IntrusiveRefCntPtr<vfs::FileSystem> VFS)
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)
: Opts(createDriverOptTable()), Diags(Diags), VFS(std::move(VFS)),
Mode(GCCMode), SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone),
LTOMode(LTOK_None), ClangExecutable(ClangExecutable),
@@ -98,12 +102,11 @@ Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple,
CCPrintOptions(false), CCPrintHeaders(false), CCLogDiagnostics(false),
CCGenDiagnostics(false), TargetTriple(TargetTriple),
CCCGenericGCCName(""), Saver(Alloc), CheckInputsExist(true),
- CCCUsePCH(true), GenReproducer(false),
- SuppressMissingInputWarning(false) {
+ GenReproducer(false), SuppressMissingInputWarning(false) {
// Provide a sane fallback if no VFS is specified.
if (!this->VFS)
- this->VFS = vfs::getRealFileSystem();
+ this->VFS = llvm::vfs::getRealFileSystem();
Name = llvm::sys::path::filename(ClangExecutable);
Dir = llvm::sys::path::parent_path(ClangExecutable);
@@ -164,6 +167,7 @@ void Driver::setDriverModeFromOption(StringRef Opt) {
}
InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings,
+ bool IsClCompatMode,
bool &ContainsError) {
llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
ContainsError = false;
@@ -171,7 +175,7 @@ InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings,
unsigned IncludedFlagsBitmask;
unsigned ExcludedFlagsBitmask;
std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) =
- getIncludeExcludeOptionFlagMasks();
+ getIncludeExcludeOptionFlagMasks(IsClCompatMode);
unsigned MissingArgIndex, MissingArgCount;
InputArgList Args =
@@ -300,6 +304,7 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
DerivedArgList *DAL = new DerivedArgList(Args);
bool HasNostdlib = Args.hasArg(options::OPT_nostdlib);
+ bool HasNostdlibxx = Args.hasArg(options::OPT_nostdlibxx);
bool HasNodefaultlib = Args.hasArg(options::OPT_nodefaultlibs);
for (Arg *A : Args) {
// Unfortunately, we have to parse some forwarding options (-Xassembler,
@@ -344,7 +349,8 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
StringRef Value = A->getValue();
// Rewrite unless -nostdlib is present.
- if (!HasNostdlib && !HasNodefaultlib && Value == "stdc++") {
+ if (!HasNostdlib && !HasNodefaultlib && !HasNostdlibxx &&
+ Value == "stdc++") {
DAL->AddFlagArg(A, Opts->getOption(options::OPT_Z_reserved_lib_stdcxx));
continue;
}
@@ -399,6 +405,13 @@ static llvm::Triple computeTargetTriple(const Driver &D,
llvm::Triple Target(llvm::Triple::normalize(TargetTriple));
+ // GNU/Hurd's triples should have been -hurd-gnu*, but were historically made
+ // -gnu* only, and we can not change this, so we have to detect that case as
+ // being the Hurd OS.
+ if (TargetTriple.find("-unknown-gnu") != StringRef::npos ||
+ TargetTriple.find("-pc-gnu") != StringRef::npos)
+ Target.setOSName("hurd");
+
// Handle Apple-specific options available here.
if (Target.isOSBinFormatMachO()) {
// If an explicit Darwin arch name is given, that trumps all.
@@ -481,6 +494,29 @@ static llvm::Triple computeTargetTriple(const Driver &D,
Target.setVendorName("intel");
}
+ // If target is MIPS adjust the target triple
+ // accordingly to provided ABI name.
+ A = Args.getLastArg(options::OPT_mabi_EQ);
+ if (A && Target.isMIPS()) {
+ StringRef ABIName = A->getValue();
+ if (ABIName == "32") {
+ Target = Target.get32BitArchVariant();
+ if (Target.getEnvironment() == llvm::Triple::GNUABI64 ||
+ Target.getEnvironment() == llvm::Triple::GNUABIN32)
+ Target.setEnvironment(llvm::Triple::GNU);
+ } else if (ABIName == "n32") {
+ Target = Target.get64BitArchVariant();
+ if (Target.getEnvironment() == llvm::Triple::GNU ||
+ Target.getEnvironment() == llvm::Triple::GNUABI64)
+ Target.setEnvironment(llvm::Triple::GNUABIN32);
+ } else if (ABIName == "64") {
+ Target = Target.get64BitArchVariant();
+ if (Target.getEnvironment() == llvm::Triple::GNU ||
+ Target.getEnvironment() == llvm::Triple::GNUABIN32)
+ Target.setEnvironment(llvm::Triple::GNUABI64);
+ }
+ }
+
return Target;
}
@@ -705,7 +741,7 @@ bool Driver::readConfigFile(StringRef FileName) {
ConfigFile = CfgFileName.str();
bool ContainErrors;
CfgOptions = llvm::make_unique<InputArgList>(
- ParseArgStrings(NewCfgArgs, ContainErrors));
+ ParseArgStrings(NewCfgArgs, IsCLMode(), ContainErrors));
if (ContainErrors) {
CfgOptions.reset();
return true;
@@ -899,7 +935,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// Arguments specified in command line.
bool ContainsError;
CLOptions = llvm::make_unique<InputArgList>(
- ParseArgStrings(ArgList.slice(1), ContainsError));
+ ParseArgStrings(ArgList.slice(1), IsCLMode(), ContainsError));
// Try parsing configuration file.
if (!ContainsError)
@@ -909,22 +945,48 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// All arguments, from both config file and command line.
InputArgList Args = std::move(HasConfigFile ? std::move(*CfgOptions)
: std::move(*CLOptions));
- if (HasConfigFile)
- for (auto *Opt : *CLOptions) {
- if (Opt->getOption().matches(options::OPT_config))
- continue;
+
+ auto appendOneArg = [&Args](const Arg *Opt, const Arg *BaseArg) {
unsigned Index = Args.MakeIndex(Opt->getSpelling());
- const Arg *BaseArg = &Opt->getBaseArg();
- if (BaseArg == Opt)
- BaseArg = nullptr;
Arg *Copy = new llvm::opt::Arg(Opt->getOption(), Opt->getSpelling(),
Index, BaseArg);
Copy->getValues() = Opt->getValues();
if (Opt->isClaimed())
Copy->claim();
Args.append(Copy);
+ };
+
+ if (HasConfigFile)
+ for (auto *Opt : *CLOptions) {
+ if (Opt->getOption().matches(options::OPT_config))
+ continue;
+ const Arg *BaseArg = &Opt->getBaseArg();
+ if (BaseArg == Opt)
+ BaseArg = nullptr;
+ appendOneArg(Opt, BaseArg);
}
+ // In CL mode, look for any pass-through arguments
+ if (IsCLMode() && !ContainsError) {
+ SmallVector<const char *, 16> CLModePassThroughArgList;
+ for (const auto *A : Args.filtered(options::OPT__SLASH_clang)) {
+ A->claim();
+ CLModePassThroughArgList.push_back(A->getValue());
+ }
+
+ if (!CLModePassThroughArgList.empty()) {
+ // Parse any pass through args using default clang processing rather
+ // than clang-cl processing.
+ auto CLModePassThroughOptions = llvm::make_unique<InputArgList>(
+ ParseArgStrings(CLModePassThroughArgList, false, ContainsError));
+
+ if (!ContainsError)
+ for (auto *Opt : *CLModePassThroughOptions) {
+ appendOneArg(Opt, nullptr);
+ }
+ }
+ }
+
// FIXME: This stuff needs to go into the Compilation, not the driver.
bool CCCPrintPhases;
@@ -947,8 +1009,6 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
CCCPrintBindings = Args.hasArg(options::OPT_ccc_print_bindings);
if (const Arg *A = Args.getLastArg(options::OPT_ccc_gcc_name))
CCCGenericGCCName = A->getValue();
- CCCUsePCH =
- Args.hasFlag(options::OPT_ccc_pch_is_pch, options::OPT_ccc_pch_is_pth);
GenReproducer = Args.hasFlag(options::OPT_gen_reproducer,
options::OPT_fno_crash_diagnostics,
!!::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH"));
@@ -1377,8 +1437,9 @@ int Driver::ExecuteCompilation(
// Otherwise, remove result files and print extra information about abnormal
// failures.
+ int Res = 0;
for (const auto &CmdPair : FailingCommands) {
- int Res = CmdPair.first;
+ int CommandRes = CmdPair.first;
const Command *FailingCommand = CmdPair.second;
// Remove result files if we're not saving temps.
@@ -1387,10 +1448,19 @@ int Driver::ExecuteCompilation(
C.CleanupFileMap(C.getResultFiles(), JA, true);
// Failure result files are valid unless we crashed.
- if (Res < 0)
+ if (CommandRes < 0)
C.CleanupFileMap(C.getFailureResultFiles(), JA, true);
}
+#if LLVM_ON_UNIX
+ // llvm/lib/Support/Unix/Signals.inc will exit with a special return code
+ // for SIGPIPE. Do not print diagnostics for this case.
+ if (CommandRes == EX_IOERR) {
+ Res = CommandRes;
+ continue;
+ }
+#endif
+
// Print extra information about abnormal failures, if possible.
//
// This is ad-hoc, but we don't want to be excessively noisy. If the result
@@ -1400,30 +1470,31 @@ int Driver::ExecuteCompilation(
// diagnostics, so always print the diagnostic there.
const Tool &FailingTool = FailingCommand->getCreator();
- if (!FailingCommand->getCreator().hasGoodDiagnostics() || Res != 1) {
+ if (!FailingCommand->getCreator().hasGoodDiagnostics() || CommandRes != 1) {
// FIXME: See FIXME above regarding result code interpretation.
- if (Res < 0)
+ if (CommandRes < 0)
Diag(clang::diag::err_drv_command_signalled)
<< FailingTool.getShortName();
else
- Diag(clang::diag::err_drv_command_failed) << FailingTool.getShortName()
- << Res;
+ Diag(clang::diag::err_drv_command_failed)
+ << FailingTool.getShortName() << CommandRes;
}
}
- return 0;
+ return Res;
}
void Driver::PrintHelp(bool ShowHidden) const {
unsigned IncludedFlagsBitmask;
unsigned ExcludedFlagsBitmask;
std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) =
- getIncludeExcludeOptionFlagMasks();
+ getIncludeExcludeOptionFlagMasks(IsCLMode());
ExcludedFlagsBitmask |= options::NoDriverOption;
if (!ShowHidden)
ExcludedFlagsBitmask |= HelpHidden;
- getOpts().PrintHelp(llvm::outs(), Name.c_str(), DriverTitle.c_str(),
+ std::string Usage = llvm::formatv("{0} [options] file...", Name).str();
+ getOpts().PrintHelp(llvm::outs(), Usage.c_str(), DriverTitle.c_str(),
IncludedFlagsBitmask, ExcludedFlagsBitmask,
/*ShowAllAliases=*/false);
}
@@ -1472,6 +1543,11 @@ void Driver::HandleAutocompletions(StringRef PassedFlags) const {
unsigned short DisableFlags =
options::NoDriverOption | options::Unsupported | options::Ignored;
+ // Distinguish "--autocomplete=-someflag" and "--autocomplete=-someflag,"
+ // because the latter indicates that the user put space before pushing tab
+ // which should end up in a file completion.
+ const bool HasSpace = PassedFlags.endswith(",");
+
// Parse PassedFlags by "," as all the command-line flags are passed to this
// function separated by ","
StringRef TargetFlags = PassedFlags;
@@ -1498,7 +1574,19 @@ void Driver::HandleAutocompletions(StringRef PassedFlags) const {
if (SuggestedCompletions.empty())
SuggestedCompletions = Opts->suggestValueCompletions(Cur, "");
- if (SuggestedCompletions.empty()) {
+ // If Flags were empty, it means the user typed `clang [tab]` where we should
+ // list all possible flags. If there was no value completion and the user
+ // pressed tab after a space, we should fall back to a file completion.
+ // We're printing a newline to be consistent with what we print at the end of
+ // this function.
+ if (SuggestedCompletions.empty() && HasSpace && !Flags.empty()) {
+ llvm::outs() << '\n';
+ return;
+ }
+
+ // When flag ends with '=' and there was no value completion, return empty
+ // string and fall back to the file autocompletion.
+ if (SuggestedCompletions.empty() && !Cur.endswith("=")) {
// If the flag is in the form of "--autocomplete=-foo",
// we were requested to print out all option names that start with "-foo".
// For example, "--autocomplete=-fsyn" is expanded to "-fsyntax-only".
@@ -1516,12 +1604,11 @@ void Driver::HandleAutocompletions(StringRef PassedFlags) const {
// deterministic order. We could sort in any way, but we chose
// case-insensitive sorting for consistency with the -help option
// which prints out options in the case-insensitive alphabetical order.
- llvm::sort(SuggestedCompletions.begin(), SuggestedCompletions.end(),
- [](StringRef A, StringRef B) {
- if (int X = A.compare_lower(B))
- return X < 0;
- return A.compare(B) > 0;
- });
+ llvm::sort(SuggestedCompletions, [](StringRef A, StringRef B) {
+ if (int X = A.compare_lower(B))
+ return X < 0;
+ return A.compare(B) > 0;
+ });
llvm::outs() << llvm::join(SuggestedCompletions, "\n") << '\n';
}
@@ -1661,17 +1748,28 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
}
if (C.getArgs().hasArg(options::OPT_print_multi_directory)) {
- for (const Multilib &Multilib : TC.getMultilibs()) {
- if (Multilib.gccSuffix().empty())
- llvm::outs() << ".\n";
- else {
- StringRef Suffix(Multilib.gccSuffix());
- assert(Suffix.front() == '/');
- llvm::outs() << Suffix.substr(1) << "\n";
- }
+ const Multilib &Multilib = TC.getMultilib();
+ if (Multilib.gccSuffix().empty())
+ llvm::outs() << ".\n";
+ else {
+ StringRef Suffix(Multilib.gccSuffix());
+ assert(Suffix.front() == '/');
+ llvm::outs() << Suffix.substr(1) << "\n";
}
return false;
}
+
+ if (C.getArgs().hasArg(options::OPT_print_target_triple)) {
+ llvm::outs() << TC.getTripleString() << "\n";
+ return false;
+ }
+
+ if (C.getArgs().hasArg(options::OPT_print_effective_triple)) {
+ const llvm::Triple Triple(TC.ComputeEffectiveClangTriple(C.getArgs()));
+ llvm::outs() << Triple.getTriple() << "\n";
+ return false;
+ }
+
return true;
}
@@ -1882,7 +1980,7 @@ static bool DiagnoseInputExistence(const Driver &D, const DerivedArgList &Args,
}
}
- if (llvm::sys::fs::exists(Twine(Path)))
+ if (D.getVFS().exists(Path))
return true;
if (D.IsCLMode()) {
@@ -1960,7 +2058,8 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
Ty = types::TY_C;
} else {
// Otherwise lookup by extension.
- // Fallback is C if invoked as C preprocessor or Object otherwise.
+ // Fallback is C if invoked as C preprocessor, C++ if invoked with
+ // clang-cl /E, or Object otherwise.
// We use a host hook here because Darwin at least has its own
// idea of what .s is.
if (const char *Ext = strrchr(Value, '.'))
@@ -1969,6 +2068,8 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
if (Ty == types::TY_INVALID) {
if (CCCIsCPP())
Ty = types::TY_C;
+ else if (IsCLMode() && Args.hasArgNoClaim(options::OPT_E))
+ Ty = types::TY_CXX;
else
Ty = types::TY_Object;
}
@@ -2223,6 +2324,18 @@ class OffloadingActionBuilder final {
// If this is an unbundling action use it as is for each CUDA toolchain.
if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(HostAction)) {
CudaDeviceActions.clear();
+ auto *IA = cast<InputAction>(UA->getInputs().back());
+ std::string FileName = IA->getInputArg().getAsString(Args);
+ // Check if the type of the file is the same as the action. Do not
+ // unbundle it if it is not. Do not unbundle .so files, for example,
+ // which are not object files.
+ if (IA->getType() == types::TY_Object &&
+ (!llvm::sys::path::has_extension(FileName) ||
+ types::lookupTypeForExtension(
+ llvm::sys::path::extension(FileName).drop_front()) !=
+ types::TY_Object))
+ return ABRT_Inactive;
+
for (auto Arch : GpuArchList) {
CudaDeviceActions.push_back(UA);
UA->registerDependentActionInfo(ToolChains[0], CudaArchToString(Arch),
@@ -2466,11 +2579,13 @@ class OffloadingActionBuilder final {
class HIPActionBuilder final : public CudaActionBuilderBase {
/// The linker inputs obtained for each device arch.
SmallVector<ActionList, 8> DeviceLinkerInputs;
+ bool Relocatable;
public:
HIPActionBuilder(Compilation &C, DerivedArgList &Args,
const Driver::InputList &Inputs)
- : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_HIP) {}
+ : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_HIP),
+ Relocatable(false) {}
bool canUseBundlerUnbundler() const override { return true; }
@@ -2479,23 +2594,70 @@ class OffloadingActionBuilder final {
phases::ID CurPhase, phases::ID FinalPhase,
PhasesTy &Phases) override {
// amdgcn does not support linking of object files, therefore we skip
- // backend and assemble phases to output LLVM IR.
- if (CudaDeviceActions.empty() || CurPhase == phases::Backend ||
+ // backend and assemble phases to output LLVM IR. Except for generating
+ // non-relocatable device coee, where we generate fat binary for device
+ // code and pass to host in Backend phase.
+ if (CudaDeviceActions.empty() ||
+ (CurPhase == phases::Backend && Relocatable) ||
CurPhase == phases::Assemble)
return ABRT_Success;
- assert((CurPhase == phases::Link ||
+ assert(((CurPhase == phases::Link && Relocatable) ||
CudaDeviceActions.size() == GpuArchList.size()) &&
"Expecting one action per GPU architecture.");
assert(!CompileHostOnly &&
"Not expecting CUDA actions in host-only compilation.");
- // Save CudaDeviceActions to DeviceLinkerInputs for each GPU subarch.
- // This happens to each device action originated from each input file.
- // Later on, device actions in DeviceLinkerInputs are used to create
- // device link actions in appendLinkDependences and the created device
- // link actions are passed to the offload action as device dependence.
- if (CurPhase == phases::Link) {
+ if (!Relocatable && CurPhase == phases::Backend) {
+ // If we are in backend phase, we attempt to generate the fat binary.
+ // We compile each arch to IR and use a link action to generate code
+ // object containing ISA. Then we use a special "link" action to create
+ // a fat binary containing all the code objects for different GPU's.
+ // The fat binary is then an input to the host action.
+ for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
+ // Create a link action to link device IR with device library
+ // and generate ISA.
+ ActionList AL;
+ AL.push_back(CudaDeviceActions[I]);
+ CudaDeviceActions[I] =
+ C.MakeAction<LinkJobAction>(AL, types::TY_Image);
+
+ // OffloadingActionBuilder propagates device arch until an offload
+ // action. Since the next action for creating fatbin does
+ // not have device arch, whereas the above link action and its input
+ // have device arch, an offload action is needed to stop the null
+ // device arch of the next action being propagated to the above link
+ // action.
+ OffloadAction::DeviceDependences DDep;
+ DDep.add(*CudaDeviceActions[I], *ToolChains.front(),
+ CudaArchToString(GpuArchList[I]), AssociatedOffloadKind);
+ CudaDeviceActions[I] = C.MakeAction<OffloadAction>(
+ DDep, CudaDeviceActions[I]->getType());
+ }
+ // Create HIP fat binary with a special "link" action.
+ CudaFatBinary =
+ C.MakeAction<LinkJobAction>(CudaDeviceActions,
+ types::TY_HIP_FATBIN);
+
+ if (!CompileDeviceOnly) {
+ DA.add(*CudaFatBinary, *ToolChains.front(), /*BoundArch=*/nullptr,
+ AssociatedOffloadKind);
+ // Clear the fat binary, it is already a dependence to an host
+ // action.
+ CudaFatBinary = nullptr;
+ }
+
+ // Remove the CUDA actions as they are already connected to an host
+ // action or fat binary.
+ CudaDeviceActions.clear();
+
+ return CompileDeviceOnly ? ABRT_Ignore_Host : ABRT_Success;
+ } else if (CurPhase == phases::Link) {
+ // Save CudaDeviceActions to DeviceLinkerInputs for each GPU subarch.
+ // This happens to each device action originated from each input file.
+ // Later on, device actions in DeviceLinkerInputs are used to create
+ // device link actions in appendLinkDependences and the created device
+ // link actions are passed to the offload action as device dependence.
DeviceLinkerInputs.resize(CudaDeviceActions.size());
auto LI = DeviceLinkerInputs.begin();
for (auto *A : CudaDeviceActions) {
@@ -2528,6 +2690,13 @@ class OffloadingActionBuilder final {
++I;
}
}
+
+ bool initialize() override {
+ Relocatable = Args.hasFlag(options::OPT_fgpu_rdc,
+ options::OPT_fno_gpu_rdc, /*Default=*/false);
+
+ return CudaActionBuilderBase::initialize();
+ }
};
/// OpenMP action builder. The host bitcode is passed to the device frontend
@@ -2548,6 +2717,8 @@ class OffloadingActionBuilder final {
getDeviceDependences(OffloadAction::DeviceDependences &DA,
phases::ID CurPhase, phases::ID FinalPhase,
PhasesTy &Phases) override {
+ if (OpenMPDeviceActions.empty())
+ return ABRT_Inactive;
// We should always have an action for each input.
assert(OpenMPDeviceActions.size() == ToolChains.size() &&
@@ -2591,6 +2762,17 @@ class OffloadingActionBuilder final {
// If this is an unbundling action use it as is for each OpenMP toolchain.
if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(HostAction)) {
OpenMPDeviceActions.clear();
+ auto *IA = cast<InputAction>(UA->getInputs().back());
+ std::string FileName = IA->getInputArg().getAsString(Args);
+ // Check if the type of the file is the same as the action. Do not
+ // unbundle it if it is not. Do not unbundle .so files, for example,
+ // which are not object files.
+ if (IA->getType() == types::TY_Object &&
+ (!llvm::sys::path::has_extension(FileName) ||
+ types::lookupTypeForExtension(
+ llvm::sys::path::extension(FileName).drop_front()) !=
+ types::TY_Object))
+ return ABRT_Inactive;
for (unsigned I = 0; I < ToolChains.size(); ++I) {
OpenMPDeviceActions.push_back(UA);
UA->registerDependentActionInfo(
@@ -2835,6 +3017,11 @@ public:
OffloadKind |= SB->getAssociatedOffloadKind();
}
+ // Do not use unbundler if the Host does not depend on device action.
+ if (OffloadKind == Action::OFK_None && CanUseBundler)
+ if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(HostAction))
+ HostAction = UA->getInputs().back();
+
return false;
}
@@ -2852,8 +3039,10 @@ public:
}
// If we can use the bundler, replace the host action by the bundling one in
- // the resulting list. Otherwise, just append the device actions.
- if (CanUseBundler && !OffloadAL.empty()) {
+ // the resulting list. Otherwise, just append the device actions. For
+ // device only compilation, HostAction is a null pointer, therefore only do
+ // this when HostAction is not a null pointer.
+ if (CanUseBundler && HostAction && !OffloadAL.empty()) {
// Add the host action to the list in order to create the bundling action.
OffloadAL.push_back(HostAction);
@@ -2971,22 +3160,9 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
}
}
- // Diagnose unsupported forms of /Yc /Yu. Ignore /Yc/Yu for now if:
- // * no filename after it
- // * both /Yc and /Yu passed but with different filenames
- // * corresponding file not also passed as /FI
+ // Ignore /Yc/Yu if both /Yc and /Yu passed but with different filenames.
Arg *YcArg = Args.getLastArg(options::OPT__SLASH_Yc);
Arg *YuArg = Args.getLastArg(options::OPT__SLASH_Yu);
- if (YcArg && YcArg->getValue()[0] == '\0') {
- Diag(clang::diag::warn_drv_ycyu_no_arg_clang_cl) << YcArg->getSpelling();
- Args.eraseArg(options::OPT__SLASH_Yc);
- YcArg = nullptr;
- }
- if (YuArg && YuArg->getValue()[0] == '\0') {
- Diag(clang::diag::warn_drv_ycyu_no_arg_clang_cl) << YuArg->getSpelling();
- Args.eraseArg(options::OPT__SLASH_Yu);
- YuArg = nullptr;
- }
if (YcArg && YuArg && strcmp(YcArg->getValue(), YuArg->getValue()) != 0) {
Diag(clang::diag::warn_drv_ycyu_different_arg_clang_cl);
Args.eraseArg(options::OPT__SLASH_Yc);
@@ -2998,9 +3174,10 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
Args.eraseArg(options::OPT__SLASH_Yc);
YcArg = nullptr;
}
- if (Args.hasArg(options::OPT__SLASH_Y_)) {
- // /Y- disables all pch handling. Rather than check for it everywhere,
- // just remove clang-cl pch-related flags here.
+ if (FinalPhase == phases::Preprocess || Args.hasArg(options::OPT__SLASH_Y_)) {
+ // If only preprocessing or /Y- is used, all pch handling is disabled.
+ // Rather than check for it everywhere, just remove clang-cl pch-related
+ // flags here.
Args.eraseArg(options::OPT__SLASH_Fp);
Args.eraseArg(options::OPT__SLASH_Yc);
Args.eraseArg(options::OPT__SLASH_Yu);
@@ -3011,6 +3188,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
OffloadingActionBuilder OffloadBuilder(C, Args, Inputs);
// Construct the actions to perform.
+ HeaderModulePrecompileJobAction *HeaderModuleAction = nullptr;
ActionList LinkerInputs;
llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PL;
@@ -3107,13 +3285,29 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
break;
}
+ // Each precompiled header file after a module file action is a module
+ // header of that same module file, rather than being compiled to a
+ // separate PCH.
+ if (Phase == phases::Precompile && HeaderModuleAction &&
+ getPrecompiledType(InputType) == types::TY_PCH) {
+ HeaderModuleAction->addModuleHeaderInput(Current);
+ Current = nullptr;
+ break;
+ }
+
+ // FIXME: Should we include any prior module file outputs as inputs of
+ // later actions in the same command line?
+
// Otherwise construct the appropriate action.
- auto *NewCurrent = ConstructPhaseAction(C, Args, Phase, Current);
+ Action *NewCurrent = ConstructPhaseAction(C, Args, Phase, Current);
// We didn't create a new action, so we will just move to the next phase.
if (NewCurrent == Current)
continue;
+ if (auto *HMA = dyn_cast<HeaderModulePrecompileJobAction>(NewCurrent))
+ HeaderModuleAction = HMA;
+
Current = NewCurrent;
// Use the current host action in any of the offloading actions, if
@@ -3193,10 +3387,25 @@ Action *Driver::ConstructPhaseAction(
types::ID OutputTy = getPrecompiledType(Input->getType());
assert(OutputTy != types::TY_INVALID &&
"Cannot precompile this input type!");
+
+ // If we're given a module name, precompile header file inputs as a
+ // module, not as a precompiled header.
+ const char *ModName = nullptr;
+ if (OutputTy == types::TY_PCH) {
+ if (Arg *A = Args.getLastArg(options::OPT_fmodule_name_EQ))
+ ModName = A->getValue();
+ if (ModName)
+ OutputTy = types::TY_ModuleFile;
+ }
+
if (Args.hasArg(options::OPT_fsyntax_only)) {
// Syntax checks should not emit a PCH file
OutputTy = types::TY_Nothing;
}
+
+ if (ModName)
+ return C.MakeAction<HeaderModulePrecompileJobAction>(Input, OutputTy,
+ ModName);
return C.MakeAction<PrecompileJobAction>(Input, OutputTy);
}
case phases::Compile: {
@@ -3449,7 +3658,7 @@ class ToolSelector final {
/// - Backend + Compile.
const Tool *
combineAssembleBackendCompile(ArrayRef<JobActionInfo> ActionInfo,
- const ActionList *&Inputs,
+ ActionList &Inputs,
ActionList &CollapsedOffloadAction) {
if (ActionInfo.size() < 3 || !canCollapseAssembleAction())
return nullptr;
@@ -3475,13 +3684,13 @@ class ToolSelector final {
if (!T->hasIntegratedAssembler())
return nullptr;
- Inputs = &CJ->getInputs();
+ Inputs = CJ->getInputs();
AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo,
/*NumElements=*/3);
return T;
}
const Tool *combineAssembleBackend(ArrayRef<JobActionInfo> ActionInfo,
- const ActionList *&Inputs,
+ ActionList &Inputs,
ActionList &CollapsedOffloadAction) {
if (ActionInfo.size() < 2 || !canCollapseAssembleAction())
return nullptr;
@@ -3508,13 +3717,13 @@ class ToolSelector final {
if (!T->hasIntegratedAssembler())
return nullptr;
- Inputs = &BJ->getInputs();
+ Inputs = BJ->getInputs();
AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo,
/*NumElements=*/2);
return T;
}
const Tool *combineBackendCompile(ArrayRef<JobActionInfo> ActionInfo,
- const ActionList *&Inputs,
+ ActionList &Inputs,
ActionList &CollapsedOffloadAction) {
if (ActionInfo.size() < 2)
return nullptr;
@@ -3546,7 +3755,7 @@ class ToolSelector final {
if (T->canEmitIR() && ((SaveTemps && !InputIsBitcode) || EmbedBitcode))
return nullptr;
- Inputs = &CJ->getInputs();
+ Inputs = CJ->getInputs();
AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo,
/*NumElements=*/2);
return T;
@@ -3556,22 +3765,28 @@ class ToolSelector final {
/// preprocessor action, and the current input is indeed a preprocessor
/// action. If combining results in the collapse of offloading actions, those
/// are appended to \a CollapsedOffloadAction.
- void combineWithPreprocessor(const Tool *T, const ActionList *&Inputs,
+ void combineWithPreprocessor(const Tool *T, ActionList &Inputs,
ActionList &CollapsedOffloadAction) {
if (!T || !canCollapsePreprocessorAction() || !T->hasIntegratedCPP())
return;
// Attempt to get a preprocessor action dependence.
ActionList PreprocessJobOffloadActions;
- auto *PJ = getPrevDependentAction(*Inputs, PreprocessJobOffloadActions);
- if (!PJ || !isa<PreprocessJobAction>(PJ))
- return;
+ ActionList NewInputs;
+ for (Action *A : Inputs) {
+ auto *PJ = getPrevDependentAction({A}, PreprocessJobOffloadActions);
+ if (!PJ || !isa<PreprocessJobAction>(PJ)) {
+ NewInputs.push_back(A);
+ continue;
+ }
- // This is legal to combine. Append any offload action we found and set the
- // current inputs to preprocessor inputs.
- CollapsedOffloadAction.append(PreprocessJobOffloadActions.begin(),
- PreprocessJobOffloadActions.end());
- Inputs = &PJ->getInputs();
+ // This is legal to combine. Append any offload action we found and add the
+ // current input to preprocessor inputs.
+ CollapsedOffloadAction.append(PreprocessJobOffloadActions.begin(),
+ PreprocessJobOffloadActions.end());
+ NewInputs.append(PJ->input_begin(), PJ->input_end());
+ }
+ Inputs = NewInputs;
}
public:
@@ -3589,7 +3804,7 @@ public:
/// connected to collapsed actions are updated accordingly. The latter enables
/// the caller of the selector to process them afterwards instead of just
/// dropping them. If no suitable tool is found, null will be returned.
- const Tool *getTool(const ActionList *&Inputs,
+ const Tool *getTool(ActionList &Inputs,
ActionList &CollapsedOffloadAction) {
//
// Get the largest chain of actions that we could combine.
@@ -3625,7 +3840,7 @@ public:
if (!T)
T = combineBackendCompile(ActionChain, Inputs, CollapsedOffloadAction);
if (!T) {
- Inputs = &BaseAction->getInputs();
+ Inputs = BaseAction->getInputs();
T = TC.SelectTool(*BaseAction);
}
@@ -3770,7 +3985,7 @@ InputInfo Driver::BuildJobsForActionNoCache(
}
- const ActionList *Inputs = &A->getInputs();
+ ActionList Inputs = A->getInputs();
const JobAction *JA = cast<JobAction>(A);
ActionList CollapsedOffloadActions;
@@ -3796,7 +4011,7 @@ InputInfo Driver::BuildJobsForActionNoCache(
// Only use pipes when there is exactly one input.
InputInfoList InputInfos;
- for (const Action *Input : *Inputs) {
+ for (const Action *Input : Inputs) {
// Treat dsymutil and verify sub-jobs as being at the top-level too, they
// shouldn't get temporary output names.
// FIXME: Clean this up.
@@ -3815,6 +4030,10 @@ InputInfo Driver::BuildJobsForActionNoCache(
if (JA->getType() == types::TY_dSYM)
BaseInput = InputInfos[0].getFilename();
+ // ... and in header module compilations, which use the module name.
+ if (auto *ModuleJA = dyn_cast<HeaderModulePrecompileJobAction>(JA))
+ BaseInput = ModuleJA->getModuleName();
+
// Append outputs of offload device jobs to the input list
if (!OffloadDependencesInputInfo.empty())
InputInfos.append(OffloadDependencesInputInfo.begin(),
@@ -4153,16 +4372,24 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
}
std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const {
- // Respect a limited subset of the '-Bprefix' functionality in GCC by
- // attempting to use this prefix when looking for file paths.
- for (const std::string &Dir : PrefixDirs) {
- if (Dir.empty())
- continue;
- SmallString<128> P(Dir[0] == '=' ? SysRoot + Dir.substr(1) : Dir);
- llvm::sys::path::append(P, Name);
- if (llvm::sys::fs::exists(Twine(P)))
- return P.str();
- }
+ // Search for Name in a list of paths.
+ auto SearchPaths = [&](const llvm::SmallVectorImpl<std::string> &P)
+ -> llvm::Optional<std::string> {
+ // Respect a limited subset of the '-Bprefix' functionality in GCC by
+ // attempting to use this prefix when looking for file paths.
+ for (const auto &Dir : P) {
+ if (Dir.empty())
+ continue;
+ SmallString<128> P(Dir[0] == '=' ? SysRoot + Dir.substr(1) : Dir);
+ llvm::sys::path::append(P, Name);
+ if (llvm::sys::fs::exists(Twine(P)))
+ return P.str().str();
+ }
+ return None;
+ };
+
+ if (auto P = SearchPaths(PrefixDirs))
+ return *P;
SmallString<128> R(ResourceDir);
llvm::sys::path::append(R, Name);
@@ -4174,14 +4401,11 @@ std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const {
if (llvm::sys::fs::exists(Twine(P)))
return P.str();
- for (const std::string &Dir : TC.getFilePaths()) {
- if (Dir.empty())
- continue;
- SmallString<128> P(Dir[0] == '=' ? SysRoot + Dir.substr(1) : Dir);
- llvm::sys::path::append(P, Name);
- if (llvm::sys::fs::exists(Twine(P)))
- return P.str();
- }
+ if (auto P = SearchPaths(TC.getLibraryPaths()))
+ return *P;
+
+ if (auto P = SearchPaths(TC.getFilePaths()))
+ return *P;
return Name;
}
@@ -4255,6 +4479,17 @@ std::string Driver::GetTemporaryPath(StringRef Prefix, StringRef Suffix) const {
return Path.str();
}
+std::string Driver::GetTemporaryDirectory(StringRef Prefix) const {
+ SmallString<128> Path;
+ std::error_code EC = llvm::sys::fs::createUniqueDirectory(Prefix, Path);
+ if (EC) {
+ Diag(clang::diag::err_unable_to_make_temp) << EC.message();
+ return "";
+ }
+
+ return Path.str();
+}
+
std::string Driver::GetClPchPath(Compilation &C, StringRef BaseName) const {
SmallString<128> Output;
if (Arg *FpArg = C.getArgs().getLastArg(options::OPT__SLASH_Fp)) {
@@ -4267,11 +4502,11 @@ std::string Driver::GetClPchPath(Compilation &C, StringRef BaseName) const {
// extension of .pch is assumed. "
if (!llvm::sys::path::has_extension(Output))
Output += ".pch";
- } else if (Arg *YcArg = C.getArgs().getLastArg(options::OPT__SLASH_Yc)) {
- Output = YcArg->getValue();
- llvm::sys::path::replace_extension(Output, ".pch");
} else {
- Output = BaseName;
+ if (Arg *YcArg = C.getArgs().getLastArg(options::OPT__SLASH_Yc))
+ Output = YcArg->getValue();
+ if (Output.empty())
+ Output = BaseName;
llvm::sys::path::replace_extension(Output, ".pch");
}
return Output.str();
@@ -4373,6 +4608,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::Contiki:
TC = llvm::make_unique<toolchains::Contiki>(*this, Target, Args);
break;
+ case llvm::Triple::Hurd:
+ TC = llvm::make_unique<toolchains::Hurd>(*this, Target, Args);
+ break;
default:
// Of these targets, Hexagon is the only one that might have
// an OS of Linux, in which case it got handled above already.
@@ -4400,6 +4638,10 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::avr:
TC = llvm::make_unique<toolchains::AVRToolChain>(*this, Target, Args);
break;
+ case llvm::Triple::msp430:
+ TC =
+ llvm::make_unique<toolchains::MSP430ToolChain>(*this, Target, Args);
+ break;
case llvm::Triple::riscv32:
case llvm::Triple::riscv64:
TC = llvm::make_unique<toolchains::RISCVToolChain>(*this, Target, Args);
@@ -4508,11 +4750,11 @@ bool Driver::GetReleaseVersion(StringRef Str,
return false;
}
-std::pair<unsigned, unsigned> Driver::getIncludeExcludeOptionFlagMasks() const {
+std::pair<unsigned, unsigned> Driver::getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const {
unsigned IncludedFlagsBitmask = 0;
unsigned ExcludedFlagsBitmask = options::NoDriverOption;
- if (Mode == CLMode) {
+ if (IsClCompatMode) {
// Include CL and Core options.
IncludedFlagsBitmask |= options::CLOption;
IncludedFlagsBitmask |= options::CoreOption;
diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp
index bd1a9bd8e3eb..8d1dfbe12d73 100644
--- a/lib/Driver/Job.cpp
+++ b/lib/Driver/Job.cpp
@@ -35,7 +35,8 @@ using namespace clang;
using namespace driver;
Command::Command(const Action &Source, const Tool &Creator,
- const char *Executable, const ArgStringList &Arguments,
+ const char *Executable,
+ const llvm::opt::ArgStringList &Arguments,
ArrayRef<InputInfo> Inputs)
: Source(Source), Creator(Creator), Executable(Executable),
Arguments(Arguments) {
@@ -315,6 +316,12 @@ void Command::setEnvironment(llvm::ArrayRef<const char *> NewEnvironment) {
int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
std::string *ErrMsg, bool *ExecutionFailed) const {
+ if (PrintInputFilenames) {
+ for (const char *Arg : InputFilenames)
+ llvm::outs() << llvm::sys::path::filename(Arg) << "\n";
+ llvm::outs().flush();
+ }
+
SmallVector<const char*, 128> Argv;
Optional<ArrayRef<StringRef>> Env;
@@ -366,7 +373,7 @@ int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
FallbackCommand::FallbackCommand(const Action &Source_, const Tool &Creator_,
const char *Executable_,
- const ArgStringList &Arguments_,
+ const llvm::opt::ArgStringList &Arguments_,
ArrayRef<InputInfo> Inputs,
std::unique_ptr<Command> Fallback_)
: Command(Source_, Creator_, Executable_, Arguments_, Inputs),
@@ -405,11 +412,9 @@ int FallbackCommand::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
return SecondaryStatus;
}
-ForceSuccessCommand::ForceSuccessCommand(const Action &Source_,
- const Tool &Creator_,
- const char *Executable_,
- const ArgStringList &Arguments_,
- ArrayRef<InputInfo> Inputs)
+ForceSuccessCommand::ForceSuccessCommand(
+ const Action &Source_, const Tool &Creator_, const char *Executable_,
+ const llvm::opt::ArgStringList &Arguments_, ArrayRef<InputInfo> Inputs)
: Command(Source_, Creator_, Executable_, Arguments_, Inputs) {}
void ForceSuccessCommand::Print(raw_ostream &OS, const char *Terminator,
diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp
index 5d3e31567ce6..1a46073aaa37 100644
--- a/lib/Driver/SanitizerArgs.cpp
+++ b/lib/Driver/SanitizerArgs.cpp
@@ -34,8 +34,9 @@ enum : SanitizerMask {
RequiresPIE = DataFlow | HWAddress | Scudo,
NeedsUnwindTables = Address | HWAddress | Thread | Memory | DataFlow,
SupportsCoverage = Address | HWAddress | KernelAddress | KernelHWAddress |
- Memory | Leak | Undefined | Integer | ImplicitConversion |
- Nullability | DataFlow | Fuzzer | FuzzerNoLink,
+ Memory | KernelMemory | Leak | Undefined | Integer |
+ ImplicitConversion | Nullability | DataFlow | Fuzzer |
+ FuzzerNoLink,
RecoverableByDefault = Undefined | Integer | ImplicitConversion | Nullability,
Unrecoverable = Unreachable | Return,
AlwaysRecoverable = KernelAddress | KernelHWAddress,
@@ -46,7 +47,7 @@ enum : SanitizerMask {
TrappingDefault = CFI,
CFIClasses =
CFIVCall | CFINVCall | CFIMFCall | CFIDerivedCast | CFIUnrelatedCast,
- CompatibleWithMinimalRuntime = TrappingSupported | Scudo,
+ CompatibleWithMinimalRuntime = TrappingSupported | Scudo | ShadowCallStack,
};
enum CoverageFeature {
@@ -206,6 +207,8 @@ bool SanitizerArgs::needsUnwindTables() const {
return Sanitizers.Mask & NeedsUnwindTables;
}
+bool SanitizerArgs::needsLTO() const { return Sanitizers.Mask & NeedsLTO; }
+
SanitizerArgs::SanitizerArgs(const ToolChain &TC,
const llvm::opt::ArgList &Args) {
SanitizerMask AllRemove = 0; // During the loop below, the accumulated set of
@@ -375,13 +378,12 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
KernelAddress | Efficiency),
std::make_pair(SafeStack, Address | HWAddress | Leak | Thread | Memory |
KernelAddress | Efficiency),
- std::make_pair(ShadowCallStack, Address | HWAddress | Leak | Thread |
- Memory | KernelAddress | Efficiency |
- SafeStack),
std::make_pair(KernelHWAddress, Address | HWAddress | Leak | Thread |
Memory | KernelAddress | Efficiency |
- SafeStack | ShadowCallStack)};
-
+ SafeStack),
+ std::make_pair(KernelMemory, Address | HWAddress | Leak | Thread |
+ Memory | KernelAddress | Efficiency |
+ Scudo | SafeStack)};
// Enable toolchain specific default sanitizers if not explicitly disabled.
SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove;
@@ -721,16 +723,38 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
options::OPT_fsanitize_address_use_after_scope,
options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);
+ AsanPoisonCustomArrayCookie = Args.hasFlag(
+ options::OPT_fsanitize_address_poison_custom_array_cookie,
+ options::OPT_fno_sanitize_address_poison_custom_array_cookie,
+ AsanPoisonCustomArrayCookie);
+
// As a workaround for a bug in gold 2.26 and earlier, dead stripping of
// globals in ASan is disabled by default on ELF targets.
// See https://sourceware.org/bugzilla/show_bug.cgi?id=19002
AsanGlobalsDeadStripping =
!TC.getTriple().isOSBinFormatELF() || TC.getTriple().isOSFuchsia() ||
Args.hasArg(options::OPT_fsanitize_address_globals_dead_stripping);
+
+ AsanUseOdrIndicator =
+ Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
+ options::OPT_fno_sanitize_address_use_odr_indicator,
+ AsanUseOdrIndicator);
} else {
AsanUseAfterScope = false;
}
+ if (AllAddedKinds & HWAddress) {
+ if (Arg *HwasanAbiArg =
+ Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {
+ HwasanAbi = HwasanAbiArg->getValue();
+ if (HwasanAbi != "platform" && HwasanAbi != "interceptor")
+ D.Diag(clang::diag::err_drv_invalid_value)
+ << HwasanAbiArg->getAsString(Args) << HwasanAbi;
+ } else {
+ HwasanAbi = "interceptor";
+ }
+ }
+
if (AllAddedKinds & SafeStack) {
// SafeStack runtime is built into the system on Fuchsia.
SafeStackRuntime = !TC.getTriple().isOSFuchsia();
@@ -894,9 +918,20 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
if (AsanUseAfterScope)
CmdArgs.push_back("-fsanitize-address-use-after-scope");
+ if (AsanPoisonCustomArrayCookie)
+ CmdArgs.push_back("-fsanitize-address-poison-custom-array-cookie");
+
if (AsanGlobalsDeadStripping)
CmdArgs.push_back("-fsanitize-address-globals-dead-stripping");
+ if (AsanUseOdrIndicator)
+ CmdArgs.push_back("-fsanitize-address-use-odr-indicator");
+
+ if (!HwasanAbi.empty()) {
+ CmdArgs.push_back("-default-function-attr");
+ CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi));
+ }
+
// MSan: Workaround for PR16386.
// ASan: This is mainly to help LSan with cases such as
// https://github.com/google/sanitizers/issues/373
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
index cf3db34688df..88a627eab6de 100644
--- a/lib/Driver/ToolChain.cpp
+++ b/lib/Driver/ToolChain.cpp
@@ -13,7 +13,6 @@
#include "ToolChains/Clang.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Sanitizers.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Config/config.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Driver.h"
@@ -39,6 +38,7 @@
#include "llvm/Support/TargetParser.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/VersionTuple.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <cassert>
#include <cstddef>
#include <cstring>
@@ -74,10 +74,17 @@ ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
const ArgList &Args)
: D(D), Triple(T), Args(Args), CachedRTTIArg(GetRTTIArgument(Args)),
CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)) {
- SmallString<128> P(D.ResourceDir);
+ SmallString<128> P;
+
+ P.assign(D.ResourceDir);
llvm::sys::path::append(P, D.getTargetTriple(), "lib");
if (getVFS().exists(P))
- getFilePaths().push_back(P.str());
+ getLibraryPaths().push_back(P.str());
+
+ P.assign(D.ResourceDir);
+ llvm::sys::path::append(P, Triple.str(), "lib");
+ if (getVFS().exists(P))
+ getLibraryPaths().push_back(P.str());
std::string CandidateLibPath = getArchSpecificLibPath();
if (getVFS().exists(CandidateLibPath))
@@ -92,7 +99,9 @@ void ToolChain::setTripleEnvironment(llvm::Triple::EnvironmentType Env) {
ToolChain::~ToolChain() = default;
-vfs::FileSystem &ToolChain::getVFS() const { return getDriver().getVFS(); }
+llvm::vfs::FileSystem &ToolChain::getVFS() const {
+ return getDriver().getVFS();
+}
bool ToolChain::useIntegratedAs() const {
return Args.hasFlag(options::OPT_fintegrated_as,
@@ -295,6 +304,7 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const {
case Action::CompileJobClass:
case Action::PrecompileJobClass:
+ case Action::HeaderModulePrecompileJobClass:
case Action::PreprocessJobClass:
case Action::AnalyzeJobClass:
case Action::MigrateJobClass:
@@ -359,15 +369,16 @@ std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component,
TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment();
const char *Prefix = IsITANMSVCWindows ? "" : "lib";
- const char *Suffix = Shared ? (Triple.isOSWindows() ? ".dll" : ".so")
+ const char *Suffix = Shared ? (Triple.isOSWindows() ? ".lib" : ".so")
: (IsITANMSVCWindows ? ".lib" : ".a");
+ if (Shared && Triple.isWindowsGNUEnvironment())
+ Suffix = ".dll.a";
- const Driver &D = getDriver();
- SmallString<128> P(D.ResourceDir);
- llvm::sys::path::append(P, D.getTargetTriple(), "lib");
- if (getVFS().exists(P)) {
+ for (const auto &LibPath : getLibraryPaths()) {
+ SmallString<128> P(LibPath);
llvm::sys::path::append(P, Prefix + Twine("clang_rt.") + Component + Suffix);
- return P.str();
+ if (getVFS().exists(P))
+ return P.str();
}
StringRef Arch = getArchNameForCompilerRTLib(*this, Args);
@@ -392,19 +403,23 @@ std::string ToolChain::getArchSpecificLibPath() const {
}
bool ToolChain::needsProfileRT(const ArgList &Args) {
- if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
- false) ||
+ if (needsGCovInstrumentation(Args) ||
Args.hasArg(options::OPT_fprofile_generate) ||
Args.hasArg(options::OPT_fprofile_generate_EQ) ||
Args.hasArg(options::OPT_fprofile_instr_generate) ||
Args.hasArg(options::OPT_fprofile_instr_generate_EQ) ||
- Args.hasArg(options::OPT_fcreate_profile) ||
- Args.hasArg(options::OPT_coverage))
+ Args.hasArg(options::OPT_fcreate_profile))
return true;
return false;
}
+bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) {
+ return Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
+ false) ||
+ Args.hasArg(options::OPT_coverage);
+}
+
Tool *ToolChain::SelectTool(const JobAction &JA) const {
if (getDriver().ShouldUseClangCompiler(JA)) return getClang();
Action::ActionClass AC = JA.getKind();
@@ -589,7 +604,7 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
// Check to see if an explicit choice to use thumb has been made via
// -mthumb. For assembler files we must check for -mthumb in the options
- // passed to the assember via -Wa or -Xassembler.
+ // passed to the assembler via -Wa or -Xassembler.
bool IsThumb = false;
if (InputType != types::TY_PP_Asm)
IsThumb = Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb,
@@ -762,6 +777,10 @@ void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
void ToolChain::AddFilePathLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
+ for (const auto &LibPath : getLibraryPaths())
+ if(LibPath.length() > 0)
+ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
+
for (const auto &LibPath : getFilePaths())
if(LibPath.length() > 0)
CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
diff --git a/lib/Driver/ToolChains/AMDGPU.cpp b/lib/Driver/ToolChains/AMDGPU.cpp
index 6b673feeadfc..a421a09891cd 100644
--- a/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/lib/Driver/ToolChains/AMDGPU.cpp
@@ -98,3 +98,16 @@ AMDGPUToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
return DAL;
}
+
+void AMDGPUToolChain::addClangTargetOptions(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadingKind) const {
+ // Default to "hidden" visibility, as object level linking will not be
+ // supported for the foreseeable future.
+ if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
+ options::OPT_fvisibility_ms_compat)) {
+ CC1Args.push_back("-fvisibility");
+ CC1Args.push_back("hidden");
+ }
+}
diff --git a/lib/Driver/ToolChains/AMDGPU.h b/lib/Driver/ToolChains/AMDGPU.h
index 36114d0dabc4..9d38eeedf59d 100644
--- a/lib/Driver/ToolChains/AMDGPU.h
+++ b/lib/Driver/ToolChains/AMDGPU.h
@@ -61,6 +61,10 @@ public:
llvm::opt::DerivedArgList *
TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
Action::OffloadKind DeviceOffloadKind) const override;
+
+ void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadKind) const override;
};
} // end namespace toolchains
diff --git a/lib/Driver/ToolChains/Arch/AArch64.cpp b/lib/Driver/ToolChains/Arch/AArch64.cpp
index 5114279b4b45..71e55fe79e27 100644
--- a/lib/Driver/ToolChains/Arch/AArch64.cpp
+++ b/lib/Driver/ToolChains/Arch/AArch64.cpp
@@ -19,10 +19,17 @@ using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;
+/// \returns true if the given triple can determine the default CPU type even
+/// if -arch is not specified.
+static bool isCPUDeterminedByTriple(const llvm::Triple &Triple) {
+ return Triple.isOSDarwin();
+}
+
/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are
/// targeting. Set \p A to the Arg corresponding to the -mcpu argument if it is
/// provided, or to nullptr otherwise.
-std::string aarch64::getAArch64TargetCPU(const ArgList &Args, Arg *&A) {
+std::string aarch64::getAArch64TargetCPU(const ArgList &Args,
+ const llvm::Triple &Triple, Arg *&A) {
std::string CPU;
// If we have -mcpu, use that.
if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) {
@@ -36,9 +43,9 @@ std::string aarch64::getAArch64TargetCPU(const ArgList &Args, Arg *&A) {
else if (CPU.size())
return CPU;
- // Make sure we pick "cyclone" if -arch is used.
- // FIXME: Should this be picked by checking the target triple instead?
- if (Args.getLastArg(options::OPT_arch))
+ // Make sure we pick "cyclone" if -arch is used or when targetting a Darwin
+ // OS.
+ if (Args.getLastArg(options::OPT_arch) || Triple.isOSDarwin())
return "cyclone";
return "generic";
@@ -152,7 +159,9 @@ getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
return getAArch64MicroArchFeaturesFromMtune(D, CPU, Args, Features);
}
-void aarch64::getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
+void aarch64::getAArch64TargetFeatures(const Driver &D,
+ const llvm::Triple &Triple,
+ const ArgList &Args,
std::vector<StringRef> &Features) {
Arg *A;
bool success = true;
@@ -162,9 +171,9 @@ void aarch64::getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
success = getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Features);
else if ((A = Args.getLastArg(options::OPT_mcpu_EQ)))
success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
- else if (Args.hasArg(options::OPT_arch))
- success = getAArch64ArchFeaturesFromMcpu(D, getAArch64TargetCPU(Args, A),
- Args, Features);
+ else if (Args.hasArg(options::OPT_arch) || isCPUDeterminedByTriple(Triple))
+ success = getAArch64ArchFeaturesFromMcpu(
+ D, getAArch64TargetCPU(Args, Triple, A), Args, Features);
if (success && (A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)))
success =
@@ -172,9 +181,10 @@ void aarch64::getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ)))
success =
getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
- else if (success && Args.hasArg(options::OPT_arch))
+ else if (success &&
+ (Args.hasArg(options::OPT_arch) || isCPUDeterminedByTriple(Triple)))
success = getAArch64MicroArchFeaturesFromMcpu(
- D, getAArch64TargetCPU(Args, A), Args, Features);
+ D, getAArch64TargetCPU(Args, Triple, A), Args, Features);
if (!success)
D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
@@ -193,17 +203,172 @@ void aarch64::getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
Features.push_back("-crc");
}
+ // Handle (arch-dependent) fp16fml/fullfp16 relationship.
+ // FIXME: this fp16fml option handling will be reimplemented after the
+ // TargetParser rewrite.
+ const auto ItRNoFullFP16 = std::find(Features.rbegin(), Features.rend(), "-fullfp16");
+ const auto ItRFP16FML = std::find(Features.rbegin(), Features.rend(), "+fp16fml");
+ if (std::find(Features.begin(), Features.end(), "+v8.4a") != Features.end()) {
+ const auto ItRFullFP16 = std::find(Features.rbegin(), Features.rend(), "+fullfp16");
+ if (ItRFullFP16 < ItRNoFullFP16 && ItRFullFP16 < ItRFP16FML) {
+ // Only entangled feature that can be to the right of this +fullfp16 is -fp16fml.
+ // Only append the +fp16fml if there is no -fp16fml after the +fullfp16.
+ if (std::find(Features.rbegin(), ItRFullFP16, "-fp16fml") == ItRFullFP16)
+ Features.push_back("+fp16fml");
+ }
+ else
+ goto fp16_fml_fallthrough;
+ }
+ else {
+fp16_fml_fallthrough:
+ // In both of these cases, putting the 'other' feature on the end of the vector will
+ // result in the same effect as placing it immediately after the current feature.
+ if (ItRNoFullFP16 < ItRFP16FML)
+ Features.push_back("-fp16fml");
+ else if (ItRNoFullFP16 > ItRFP16FML)
+ Features.push_back("+fullfp16");
+ }
+
+ // FIXME: this needs reimplementation too after the TargetParser rewrite
+ //
+ // Context sensitive meaning of Crypto:
+ // 1) For Arch >= ARMv8.4a: crypto = sm4 + sha3 + sha2 + aes
+ // 2) For Arch <= ARMv8.3a: crypto = sha2 + aes
+ const auto ItBegin = Features.begin();
+ const auto ItEnd = Features.end();
+ const auto ItRBegin = Features.rbegin();
+ const auto ItREnd = Features.rend();
+ const auto ItRCrypto = std::find(ItRBegin, ItREnd, "+crypto");
+ const auto ItRNoCrypto = std::find(ItRBegin, ItREnd, "-crypto");
+ const auto HasCrypto = ItRCrypto != ItREnd;
+ const auto HasNoCrypto = ItRNoCrypto != ItREnd;
+ const ptrdiff_t PosCrypto = ItRCrypto - ItRBegin;
+ const ptrdiff_t PosNoCrypto = ItRNoCrypto - ItRBegin;
+
+ bool NoCrypto = false;
+ if (HasCrypto && HasNoCrypto) {
+ if (PosNoCrypto < PosCrypto)
+ NoCrypto = true;
+ }
+
+ if (std::find(ItBegin, ItEnd, "+v8.4a") != ItEnd) {
+ if (HasCrypto && !NoCrypto) {
+ // Check if we have NOT disabled an algorithm with something like:
+ // +crypto, -algorithm
+ // And if "-algorithm" does not occur, we enable that crypto algorithm.
+ const bool HasSM4 = (std::find(ItBegin, ItEnd, "-sm4") == ItEnd);
+ const bool HasSHA3 = (std::find(ItBegin, ItEnd, "-sha3") == ItEnd);
+ const bool HasSHA2 = (std::find(ItBegin, ItEnd, "-sha2") == ItEnd);
+ const bool HasAES = (std::find(ItBegin, ItEnd, "-aes") == ItEnd);
+ if (HasSM4)
+ Features.push_back("+sm4");
+ if (HasSHA3)
+ Features.push_back("+sha3");
+ if (HasSHA2)
+ Features.push_back("+sha2");
+ if (HasAES)
+ Features.push_back("+aes");
+ } else if (HasNoCrypto) {
+ // Check if we have NOT enabled a crypto algorithm with something like:
+ // -crypto, +algorithm
+ // And if "+algorithm" does not occur, we disable that crypto algorithm.
+ const bool HasSM4 = (std::find(ItBegin, ItEnd, "+sm4") != ItEnd);
+ const bool HasSHA3 = (std::find(ItBegin, ItEnd, "+sha3") != ItEnd);
+ const bool HasSHA2 = (std::find(ItBegin, ItEnd, "+sha2") != ItEnd);
+ const bool HasAES = (std::find(ItBegin, ItEnd, "+aes") != ItEnd);
+ if (!HasSM4)
+ Features.push_back("-sm4");
+ if (!HasSHA3)
+ Features.push_back("-sha3");
+ if (!HasSHA2)
+ Features.push_back("-sha2");
+ if (!HasAES)
+ Features.push_back("-aes");
+ }
+ } else {
+ if (HasCrypto && !NoCrypto) {
+ const bool HasSHA2 = (std::find(ItBegin, ItEnd, "-sha2") == ItEnd);
+ const bool HasAES = (std::find(ItBegin, ItEnd, "-aes") == ItEnd);
+ if (HasSHA2)
+ Features.push_back("+sha2");
+ if (HasAES)
+ Features.push_back("+aes");
+ } else if (HasNoCrypto) {
+ const bool HasSHA2 = (std::find(ItBegin, ItEnd, "+sha2") != ItEnd);
+ const bool HasAES = (std::find(ItBegin, ItEnd, "+aes") != ItEnd);
+ const bool HasV82a = (std::find(ItBegin, ItEnd, "+v8.2a") != ItEnd);
+ const bool HasV83a = (std::find(ItBegin, ItEnd, "+v8.3a") != ItEnd);
+ const bool HasV84a = (std::find(ItBegin, ItEnd, "+v8.4a") != ItEnd);
+ if (!HasSHA2)
+ Features.push_back("-sha2");
+ if (!HasAES)
+ Features.push_back("-aes");
+ if (HasV82a || HasV83a || HasV84a) {
+ Features.push_back("-sm4");
+ Features.push_back("-sha3");
+ }
+ }
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
options::OPT_munaligned_access))
if (A->getOption().matches(options::OPT_mno_unaligned_access))
Features.push_back("+strict-align");
+ 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_x18))
Features.push_back("+reserve-x18");
if (Args.hasArg(options::OPT_ffixed_x20))
Features.push_back("+reserve-x20");
+ if (Args.hasArg(options::OPT_fcall_saved_x8))
+ Features.push_back("+call-saved-x8");
+
+ if (Args.hasArg(options::OPT_fcall_saved_x9))
+ Features.push_back("+call-saved-x9");
+
+ if (Args.hasArg(options::OPT_fcall_saved_x10))
+ Features.push_back("+call-saved-x10");
+
+ if (Args.hasArg(options::OPT_fcall_saved_x11))
+ Features.push_back("+call-saved-x11");
+
+ if (Args.hasArg(options::OPT_fcall_saved_x12))
+ Features.push_back("+call-saved-x12");
+
+ if (Args.hasArg(options::OPT_fcall_saved_x13))
+ Features.push_back("+call-saved-x13");
+
+ if (Args.hasArg(options::OPT_fcall_saved_x14))
+ Features.push_back("+call-saved-x14");
+
+ if (Args.hasArg(options::OPT_fcall_saved_x15))
+ Features.push_back("+call-saved-x15");
+
+ if (Args.hasArg(options::OPT_fcall_saved_x18))
+ Features.push_back("+call-saved-x18");
+
if (Args.hasArg(options::OPT_mno_neg_immediates))
Features.push_back("+no-neg-immediates");
}
diff --git a/lib/Driver/ToolChains/Arch/AArch64.h b/lib/Driver/ToolChains/Arch/AArch64.h
index 62e419cc19f7..5f6148ebd6c4 100644
--- a/lib/Driver/ToolChains/Arch/AArch64.h
+++ b/lib/Driver/ToolChains/Arch/AArch64.h
@@ -21,11 +21,12 @@ namespace driver {
namespace tools {
namespace aarch64 {
-void getAArch64TargetFeatures(const Driver &D, const llvm::opt::ArgList &Args,
+void getAArch64TargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args,
std::vector<llvm::StringRef> &Features);
std::string getAArch64TargetCPU(const llvm::opt::ArgList &Args,
- llvm::opt::Arg *&A);
+ const llvm::Triple &Triple, llvm::opt::Arg *&A);
} // end namespace aarch64
} // end namespace target
diff --git a/lib/Driver/ToolChains/Arch/ARM.cpp b/lib/Driver/ToolChains/Arch/ARM.cpp
index 886d947c586b..f55efc1a22e3 100644
--- a/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -378,6 +378,13 @@ void arm::getARMTargetFeatures(const ToolChain &TC,
Features);
} else if (FPUArg) {
getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features);
+ } else if (Triple.isAndroid() && getARMSubArchVersionNumber(Triple) >= 7) {
+ // Android mandates minimum FPU requirements based on OS version.
+ const char *AndroidFPU =
+ Triple.isAndroidVersionLT(23) ? "vfpv3-d16" : "neon";
+ if (!llvm::ARM::getFPUFeatures(llvm::ARM::parseFPU(AndroidFPU), Features))
+ D.Diag(clang::diag::err_drv_clang_unsupported)
+ << std::string("-mfpu=") + AndroidFPU;
}
// Honor -mhwdiv=. ClangAs gives preference to -Wa,-mhwdiv=.
@@ -391,6 +398,33 @@ void arm::getARMTargetFeatures(const ToolChain &TC,
} else if (HDivArg)
getARMHWDivFeatures(D, HDivArg, Args, HDivArg->getValue(), Features);
+ // Handle (arch-dependent) fp16fml/fullfp16 relationship.
+ // Must happen before any features are disabled due to soft-float.
+ // FIXME: this fp16fml option handling will be reimplemented after the
+ // TargetParser rewrite.
+ const auto ItRNoFullFP16 = std::find(Features.rbegin(), Features.rend(), "-fullfp16");
+ const auto ItRFP16FML = std::find(Features.rbegin(), Features.rend(), "+fp16fml");
+ if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8_4a) {
+ const auto ItRFullFP16 = std::find(Features.rbegin(), Features.rend(), "+fullfp16");
+ if (ItRFullFP16 < ItRNoFullFP16 && ItRFullFP16 < ItRFP16FML) {
+ // Only entangled feature that can be to the right of this +fullfp16 is -fp16fml.
+ // Only append the +fp16fml if there is no -fp16fml after the +fullfp16.
+ if (std::find(Features.rbegin(), ItRFullFP16, "-fp16fml") == ItRFullFP16)
+ Features.push_back("+fp16fml");
+ }
+ else
+ goto fp16_fml_fallthrough;
+ }
+ else {
+fp16_fml_fallthrough:
+ // In both of these cases, putting the 'other' feature on the end of the vector will
+ // result in the same effect as placing it immediately after the current feature.
+ if (ItRNoFullFP16 < ItRFP16FML)
+ Features.push_back("-fp16fml");
+ else if (ItRNoFullFP16 > ItRFP16FML)
+ Features.push_back("+fullfp16");
+ }
+
// Setting -msoft-float/-mfloat-abi=soft effectively disables the FPU (GCC
// ignores the -mfpu options in this case).
// Note that the ABI can also be set implicitly by the target selected.
@@ -404,7 +438,7 @@ void arm::getARMTargetFeatures(const ToolChain &TC,
// now just be explicit and disable all known dependent features
// as well.
for (std::string Feature : {"vfp2", "vfp3", "vfp4", "fp-armv8", "fullfp16",
- "neon", "crypto", "dotprod"})
+ "neon", "crypto", "dotprod", "fp16fml"})
if (std::find(std::begin(Features), std::end(Features), "+" + Feature) != std::end(Features))
Features.push_back(Args.MakeArgString("-" + Feature));
}
@@ -417,6 +451,26 @@ void arm::getARMTargetFeatures(const ToolChain &TC,
Features.push_back("-crc");
}
+ // For Arch >= ARMv8.0: crypto = sha2 + aes
+ // FIXME: this needs reimplementation after the TargetParser rewrite
+ if (ArchName.find_lower("armv8a") != StringRef::npos ||
+ ArchName.find_lower("armv8.1a") != StringRef::npos ||
+ ArchName.find_lower("armv8.2a") != StringRef::npos ||
+ ArchName.find_lower("armv8.3a") != StringRef::npos ||
+ ArchName.find_lower("armv8.4a") != StringRef::npos) {
+ if (ArchName.find_lower("+crypto") != StringRef::npos) {
+ if (ArchName.find_lower("+nosha2") == StringRef::npos)
+ Features.push_back("+sha2");
+ if (ArchName.find_lower("+noaes") == StringRef::npos)
+ Features.push_back("+aes");
+ } else if (ArchName.find_lower("-crypto") != StringRef::npos) {
+ if (ArchName.find_lower("+sha2") == StringRef::npos)
+ Features.push_back("-sha2");
+ if (ArchName.find_lower("+aes") == StringRef::npos)
+ Features.push_back("-aes");
+ }
+ }
+
// Look for the last occurrence of -mlong-calls or -mno-long-calls. If
// neither options are specified, see if we are compiling for kernel/kext and
// decide whether to pass "+long-calls" based on the OS and its version.
@@ -589,7 +643,7 @@ StringRef arm::getLLVMArchSuffixForARM(StringRef CPU, StringRef Arch,
return llvm::ARM::getSubArch(ArchKind);
}
-void arm::appendEBLinkFlags(const ArgList &Args, ArgStringList &CmdArgs,
+void arm::appendBE8LinkFlag(const ArgList &Args, ArgStringList &CmdArgs,
const llvm::Triple &Triple) {
if (Args.hasArg(options::OPT_r))
return;
diff --git a/lib/Driver/ToolChains/Arch/ARM.h b/lib/Driver/ToolChains/Arch/ARM.h
index c1dc16884033..9f0dc4ea2e25 100644
--- a/lib/Driver/ToolChains/Arch/ARM.h
+++ b/lib/Driver/ToolChains/Arch/ARM.h
@@ -29,7 +29,7 @@ StringRef getARMCPUForMArch(llvm::StringRef Arch, const llvm::Triple &Triple);
StringRef getLLVMArchSuffixForARM(llvm::StringRef CPU, llvm::StringRef Arch,
const llvm::Triple &Triple);
-void appendEBLinkFlags(const llvm::opt::ArgList &Args,
+void appendBE8LinkFlag(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
const llvm::Triple &Triple);
enum class ReadTPMode {
diff --git a/lib/Driver/ToolChains/Arch/Mips.cpp b/lib/Driver/ToolChains/Arch/Mips.cpp
index 6d814631d05f..e10a5e1c773f 100644
--- a/lib/Driver/ToolChains/Arch/Mips.cpp
+++ b/lib/Driver/ToolChains/Arch/Mips.cpp
@@ -35,6 +35,11 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
DefMips64CPU = "mips64r6";
}
+ if (Triple.getSubArch() == llvm::Triple::MipsSubArch_r6) {
+ DefMips32CPU = "mips32r6";
+ DefMips64CPU = "mips64r6";
+ }
+
// MIPS64r6 is the default for Android MIPS64 (mips64el-linux-android).
if (Triple.isAndroid()) {
DefMips32CPU = "mips32";
@@ -42,12 +47,12 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
}
// MIPS3 is the default for mips64*-unknown-openbsd.
- if (Triple.getOS() == llvm::Triple::OpenBSD)
+ if (Triple.isOSOpenBSD())
DefMips64CPU = "mips3";
// MIPS2 is the default for mips(el)?-unknown-freebsd.
// MIPS3 is the default for mips64(el)?-unknown-freebsd.
- if (Triple.getOS() == llvm::Triple::FreeBSD) {
+ if (Triple.isOSFreeBSD()) {
DefMips32CPU = "mips2";
DefMips64CPU = "mips3";
}
@@ -82,6 +87,9 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
}
}
+ if (ABIName.empty() && (Triple.getEnvironment() == llvm::Triple::GNUABIN32))
+ ABIName = "n32";
+
if (ABIName.empty() &&
(Triple.getVendor() == llvm::Triple::MipsTechnologies ||
Triple.getVendor() == llvm::Triple::ImaginationTechnologies)) {
diff --git a/lib/Driver/ToolChains/Arch/PPC.cpp b/lib/Driver/ToolChains/Arch/PPC.cpp
index f6a95962ace3..791f1206cf25 100644
--- a/lib/Driver/ToolChains/Arch/PPC.cpp
+++ b/lib/Driver/ToolChains/Arch/PPC.cpp
@@ -107,15 +107,19 @@ void ppc::getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,
if (FloatABI == ppc::FloatABI::Soft)
Features.push_back("-hard-float");
- ppc::ReadGOTPtrMode ReadGOT = ppc::getPPCReadGOTPtrMode(D, Args);
+ ppc::ReadGOTPtrMode ReadGOT = ppc::getPPCReadGOTPtrMode(D, Triple, Args);
if (ReadGOT == ppc::ReadGOTPtrMode::SecurePlt)
Features.push_back("+secure-plt");
}
-ppc::ReadGOTPtrMode ppc::getPPCReadGOTPtrMode(const Driver &D, const ArgList &Args) {
+ppc::ReadGOTPtrMode ppc::getPPCReadGOTPtrMode(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args) {
if (Args.getLastArg(options::OPT_msecure_plt))
return ppc::ReadGOTPtrMode::SecurePlt;
- return ppc::ReadGOTPtrMode::Bss;
+ if (Triple.isOSOpenBSD())
+ return ppc::ReadGOTPtrMode::SecurePlt;
+ else
+ return ppc::ReadGOTPtrMode::Bss;
}
ppc::FloatABI ppc::getPPCFloatABI(const Driver &D, const ArgList &Args) {
diff --git a/lib/Driver/ToolChains/Arch/PPC.h b/lib/Driver/ToolChains/Arch/PPC.h
index 3acee91a2ac3..4f3cd688ca39 100644
--- a/lib/Driver/ToolChains/Arch/PPC.h
+++ b/lib/Driver/ToolChains/Arch/PPC.h
@@ -38,7 +38,7 @@ FloatABI getPPCFloatABI(const Driver &D, const llvm::opt::ArgList &Args);
std::string getPPCTargetCPU(const llvm::opt::ArgList &Args);
const char *getPPCAsmModeForCPU(StringRef Name);
-ReadGOTPtrMode getPPCReadGOTPtrMode(const Driver &D,
+ReadGOTPtrMode getPPCReadGOTPtrMode(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
void getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,
diff --git a/lib/Driver/ToolChains/Arch/X86.cpp b/lib/Driver/ToolChains/Arch/X86.cpp
index 7a4f836d2e1a..45648945d5ef 100644
--- a/lib/Driver/ToolChains/Arch/X86.cpp
+++ b/lib/Driver/ToolChains/Arch/X86.cpp
@@ -23,12 +23,8 @@ using namespace llvm::opt;
const char *x86::getX86TargetCPU(const ArgList &Args,
const llvm::Triple &Triple) {
if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ)) {
- if (StringRef(A->getValue()) != "native") {
- if (Triple.isOSDarwin() && Triple.getArchName() == "x86_64h")
- return "core-avx2";
-
+ if (StringRef(A->getValue()) != "native")
return A->getValue();
- }
// FIXME: Reject attempts to use -march=native unless the target matches
// the host.
@@ -144,6 +140,34 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
Features.push_back("+ssse3");
}
+ // Translate the high level `-mretpoline` flag to the specific target feature
+ // flags. We also detect if the user asked for retpoline external thunks but
+ // failed to ask for retpolines themselves (through any of the different
+ // flags). This is a bit hacky but keeps existing usages working. We should
+ // consider deprecating this and instead warn if the user requests external
+ // retpoline thunks and *doesn't* request some form of retpolines.
+ if (Args.hasArgNoClaim(options::OPT_mretpoline, options::OPT_mno_retpoline,
+ options::OPT_mspeculative_load_hardening,
+ options::OPT_mno_speculative_load_hardening)) {
+ if (Args.hasFlag(options::OPT_mretpoline, options::OPT_mno_retpoline,
+ false)) {
+ Features.push_back("+retpoline-indirect-calls");
+ Features.push_back("+retpoline-indirect-branches");
+ } else if (Args.hasFlag(options::OPT_mspeculative_load_hardening,
+ options::OPT_mno_speculative_load_hardening,
+ false)) {
+ // On x86, speculative load hardening relies on at least using retpolines
+ // for indirect calls.
+ Features.push_back("+retpoline-indirect-calls");
+ }
+ } else if (Args.hasFlag(options::OPT_mretpoline_external_thunk,
+ options::OPT_mno_retpoline_external_thunk, false)) {
+ // FIXME: Add a warning about failing to specify `-mretpoline` and
+ // eventually switch to an error here.
+ Features.push_back("+retpoline-indirect-calls");
+ Features.push_back("+retpoline-indirect-branches");
+ }
+
// Now add any that the user explicitly requested on the command line,
// which may override the defaults.
handleTargetFeaturesGroup(Args, Features, options::OPT_m_x86_Features_Group);
diff --git a/lib/Driver/ToolChains/BareMetal.cpp b/lib/Driver/ToolChains/BareMetal.cpp
index c302d647b973..31d16922cc43 100644
--- a/lib/Driver/ToolChains/BareMetal.cpp
+++ b/lib/Driver/ToolChains/BareMetal.cpp
@@ -13,13 +13,13 @@
#include "InputInfo.h"
#include "Gnu.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm::opt;
@@ -119,10 +119,11 @@ void BareMetal::AddClangCXXStdlibIncludeArgs(
std::error_code EC;
Generic_GCC::GCCVersion Version = {"", -1, -1, -1, "", "", ""};
// Walk the subdirs, and find the one with the newest gcc version:
- for (vfs::directory_iterator LI =
- getDriver().getVFS().dir_begin(Dir.str(), EC), LE;
+ for (llvm::vfs::directory_iterator
+ LI = getDriver().getVFS().dir_begin(Dir.str(), EC),
+ LE;
!EC && LI != LE; LI = LI.increment(EC)) {
- StringRef VersionText = llvm::sys::path::filename(LI->getName());
+ StringRef VersionText = llvm::sys::path::filename(LI->path());
auto CandidateVersion = Generic_GCC::GCCVersion::Parse(VersionText);
if (CandidateVersion.Major == -1)
continue;
diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp
index 8e9c4c6aecb8..75f16898dfaf 100644
--- a/lib/Driver/ToolChains/Clang.cpp
+++ b/lib/Driver/ToolChains/Clang.cpp
@@ -19,12 +19,14 @@
#include "AMDGPU.h"
#include "CommonArgs.h"
#include "Hexagon.h"
+#include "MSP430.h"
#include "InputInfo.h"
#include "PS4CPU.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Version.h"
+#include "clang/Driver/Distro.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
@@ -341,7 +343,7 @@ static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
break;
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
- aarch64::getAArch64TargetFeatures(D, Args, Features);
+ aarch64::getAArch64TargetFeatures(D, Triple, Args, Features);
break;
case llvm::Triple::x86:
case llvm::Triple::x86_64:
@@ -363,6 +365,8 @@ static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
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.
@@ -493,6 +497,8 @@ static codegenoptions::DebugInfoKind DebugLevelToInfoKind(const Arg &A) {
if (A.getOption().matches(options::OPT_gline_tables_only) ||
A.getOption().matches(options::OPT_ggdb1))
return codegenoptions::DebugLineTablesOnly;
+ if (A.getOption().matches(options::OPT_gline_directives_only))
+ return codegenoptions::DebugDirectivesOnly;
return codegenoptions::LimitedDebugInfo;
}
@@ -524,11 +530,12 @@ static bool useFramePointerForTargetByDefault(const ArgList &Args,
break;
}
- if (Triple.getOS() == llvm::Triple::NetBSD) {
+ if (Triple.isOSNetBSD()) {
return !areOptimizationsEnabled(Args);
}
- if (Triple.isOSLinux() || Triple.getOS() == llvm::Triple::CloudABI) {
+ if (Triple.isOSLinux() || Triple.getOS() == llvm::Triple::CloudABI ||
+ Triple.isOSHurd()) {
switch (Triple.getArch()) {
// Don't use a frame pointer on linux if optimizing for certain targets.
case llvm::Triple::mips64:
@@ -800,6 +807,29 @@ static void addPGOAndCoverageFlags(Compilation &C, const Driver &D,
CmdArgs.push_back("-fcoverage-mapping");
}
+ if (Args.hasArg(options::OPT_fprofile_exclude_files_EQ)) {
+ auto *Arg = Args.getLastArg(options::OPT_fprofile_exclude_files_EQ);
+ if (!Args.hasArg(options::OPT_coverage))
+ D.Diag(clang::diag::err_drv_argument_only_allowed_with)
+ << "-fprofile-exclude-files="
+ << "--coverage";
+
+ StringRef v = Arg->getValue();
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-fprofile-exclude-files=" + v)));
+ }
+
+ if (Args.hasArg(options::OPT_fprofile_filter_files_EQ)) {
+ auto *Arg = Args.getLastArg(options::OPT_fprofile_filter_files_EQ);
+ if (!Args.hasArg(options::OPT_coverage))
+ D.Diag(clang::diag::err_drv_argument_only_allowed_with)
+ << "-fprofile-filter-files="
+ << "--coverage";
+
+ StringRef v = Arg->getValue();
+ CmdArgs.push_back(Args.MakeArgString(Twine("-fprofile-filter-files=" + v)));
+ }
+
if (C.getArgs().hasArg(options::OPT_c) ||
C.getArgs().hasArg(options::OPT_S)) {
if (Output.isFilename()) {
@@ -889,6 +919,9 @@ static void RenderDebugEnablingArgs(const ArgList &Args, ArgStringList &CmdArgs,
unsigned DwarfVersion,
llvm::DebuggerKind DebuggerTuning) {
switch (DebugInfoKind) {
+ case codegenoptions::DebugDirectivesOnly:
+ CmdArgs.push_back("-debug-info-kind=line-directives-only");
+ break;
case codegenoptions::DebugLineTablesOnly:
CmdArgs.push_back("-debug-info-kind=line-tables-only");
break;
@@ -1100,10 +1133,19 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
StringRef ThroughHeader = YcArg ? YcArg->getValue() : YuArg->getValue();
if (!isa<PrecompileJobAction>(JA)) {
CmdArgs.push_back("-include-pch");
- CmdArgs.push_back(Args.MakeArgString(D.GetClPchPath(C, ThroughHeader)));
+ CmdArgs.push_back(Args.MakeArgString(D.GetClPchPath(
+ C, !ThroughHeader.empty()
+ ? ThroughHeader
+ : llvm::sys::path::filename(Inputs[0].getBaseInput()))));
+ }
+
+ if (ThroughHeader.empty()) {
+ CmdArgs.push_back(Args.MakeArgString(
+ Twine("-pch-through-hdrstop-") + (YcArg ? "create" : "use")));
+ } else {
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-pch-through-header=") + ThroughHeader));
}
- CmdArgs.push_back(
- Args.MakeArgString(Twine("-pch-through-header=") + ThroughHeader));
}
}
@@ -1114,42 +1156,26 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
bool IsFirstImplicitInclude = !RenderedImplicitInclude;
RenderedImplicitInclude = true;
- // Use PCH if the user requested it.
- bool UsePCH = D.CCCUsePCH;
-
- bool FoundPTH = false;
bool FoundPCH = false;
SmallString<128> P(A->getValue());
// We want the files to have a name like foo.h.pch. Add a dummy extension
// so that replace_extension does the right thing.
P += ".dummy";
- if (UsePCH) {
- llvm::sys::path::replace_extension(P, "pch");
- if (llvm::sys::fs::exists(P))
- FoundPCH = true;
- }
+ llvm::sys::path::replace_extension(P, "pch");
+ if (llvm::sys::fs::exists(P))
+ FoundPCH = true;
if (!FoundPCH) {
- llvm::sys::path::replace_extension(P, "pth");
- if (llvm::sys::fs::exists(P))
- FoundPTH = true;
- }
-
- if (!FoundPCH && !FoundPTH) {
llvm::sys::path::replace_extension(P, "gch");
if (llvm::sys::fs::exists(P)) {
- FoundPCH = UsePCH;
- FoundPTH = !UsePCH;
+ FoundPCH = true;
}
}
- if (FoundPCH || FoundPTH) {
+ if (FoundPCH) {
if (IsFirstImplicitInclude) {
A->claim();
- if (UsePCH)
- CmdArgs.push_back("-include-pch");
- else
- CmdArgs.push_back("-include-pth");
+ CmdArgs.push_back("-include-pch");
CmdArgs.push_back(Args.MakeArgString(P));
continue;
} else {
@@ -1283,21 +1309,28 @@ static bool isNoCommonDefault(const llvm::Triple &Triple) {
}
}
-void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args,
- ArgStringList &CmdArgs, bool KernelOrKext) const {
+namespace {
+void RenderARMABI(const llvm::Triple &Triple, const ArgList &Args,
+ ArgStringList &CmdArgs) {
// Select the ABI to use.
// FIXME: Support -meabi.
// FIXME: Parts of this are duplicated in the backend, unify this somehow.
const char *ABIName = nullptr;
- if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
+ if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
ABIName = A->getValue();
- else {
+ } else {
std::string CPU = getCPUName(Args, Triple, /*FromAs*/ false);
ABIName = llvm::ARM::computeDefaultTargetABI(Triple, CPU).data();
}
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName);
+}
+}
+
+void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args,
+ ArgStringList &CmdArgs, bool KernelOrKext) const {
+ RenderARMABI(Triple, Args, CmdArgs);
// Determine floating point ABI from the options & target defaults.
arm::FloatABI ABI = arm::getARMFloatABI(getToolChain(), Args);
@@ -1409,19 +1442,59 @@ void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple,
}
}
-void Clang::AddAArch64TargetArgs(const ArgList &Args,
- ArgStringList &CmdArgs) const {
- const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
+// 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;
- if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) ||
- Args.hasArg(options::OPT_mkernel) ||
- Args.hasArg(options::OPT_fapple_kext))
- CmdArgs.push_back("-disable-red-zone");
+ 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++;
+ }
+ }
- if (!Args.hasFlag(options::OPT_mimplicit_float,
- options::OPT_mno_implicit_float, true))
- CmdArgs.push_back("-no-implicit-float");
+ return std::make_tuple(Scope, Key, IndirectBranches);
+}
+namespace {
+void RenderAArch64ABI(const llvm::Triple &Triple, const ArgList &Args,
+ ArgStringList &CmdArgs) {
const char *ABIName = nullptr;
if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
ABIName = A->getValue();
@@ -1432,6 +1505,23 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName);
+}
+}
+
+void Clang::AddAArch64TargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
+
+ if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) ||
+ Args.hasArg(options::OPT_mkernel) ||
+ Args.hasArg(options::OPT_fapple_kext))
+ CmdArgs.push_back("-disable-red-zone");
+
+ if (!Args.hasFlag(options::OPT_mimplicit_float,
+ options::OPT_mno_implicit_float, true))
+ CmdArgs.push_back("-no-implicit-float");
+
+ RenderAArch64ABI(Triple, Args, CmdArgs);
if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a53_835769,
options::OPT_mno_fix_cortex_a53_835769)) {
@@ -1455,6 +1545,35 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
else
CmdArgs.push_back("-aarch64-enable-global-merge=true");
}
+
+ // Enable/disable return address signing and indirect branch targets.
+ if (Arg *A = Args.getLastArg(options::OPT_msign_return_address_EQ,
+ options::OPT_mbranch_protection_EQ)) {
+
+ const Driver &D = getToolChain().getDriver();
+
+ StringRef Scope, Key;
+ bool IndirectBranches;
+
+ if (A->getOption().matches(options::OPT_msign_return_address_EQ)) {
+ Scope = A->getValue();
+ if (!Scope.equals("none") && !Scope.equals("non-leaf") &&
+ !Scope.equals("all"))
+ D.Diag(diag::err_invalid_branch_protection)
+ << Scope << A->getAsString(Args);
+ Key = "a_key";
+ IndirectBranches = false;
+ } else
+ std::tie(Scope, Key, IndirectBranches) =
+ ParseAArch64BranchProtection(D, Args, A);
+
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-msign-return-address=") + Scope));
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-msign-return-address-key=") + Key));
+ if (IndirectBranches)
+ CmdArgs.push_back("-mbranch-target-enforce");
+ }
}
void Clang::AddMIPSTargetArgs(const ArgList &Args,
@@ -1706,6 +1825,10 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
Args.hasArg(options::OPT_fapple_kext))
CmdArgs.push_back("-disable-red-zone");
+ if (!Args.hasFlag(options::OPT_mtls_direct_seg_refs,
+ options::OPT_mno_tls_direct_seg_refs, true))
+ CmdArgs.push_back("-mno-tls-direct-seg-refs");
+
// Default to avoid implicit floating-point for kernel/kext code, but allow
// that to be overridden with -mno-soft-float.
bool NoImplicitFloat = (Args.hasArg(options::OPT_mkernel) ||
@@ -2033,6 +2156,9 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
}
CmdArgs.push_back(Value.data());
TakeNextArg = true;
+ } else if (Value == "-fdebug-compilation-dir") {
+ CmdArgs.push_back("-fdebug-compilation-dir");
+ TakeNextArg = true;
} else {
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Value;
@@ -2045,6 +2171,11 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
CmdArgs.push_back("-target-feature");
CmdArgs.push_back(MipsTargetFeature);
}
+
+ // forward -fembed-bitcode to assmebler
+ if (C.getDriver().embedBitcodeEnabled() ||
+ C.getDriver().embedBitcodeMarkerOnly())
+ Args.AddLastArg(CmdArgs, options::OPT_fembed_bitcode_EQ);
}
static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
@@ -2066,6 +2197,11 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
StringRef DenormalFPMath = "";
StringRef FPContract = "";
+ if (const Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
+ CmdArgs.push_back("-mlimit-float-precision");
+ CmdArgs.push_back(A->getValue());
+ }
+
for (const Arg *A : Args) {
switch (A->getOption().getID()) {
// If this isn't an FP option skip the claim below
@@ -2228,8 +2364,6 @@ static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs,
// Treat blocks as analysis entry points.
CmdArgs.push_back("-analyzer-opt-analyze-nested-blocks");
- CmdArgs.push_back("-analyzer-eagerly-assume");
-
// Add default argument set.
if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) {
CmdArgs.push_back("-analyzer-checker=core");
@@ -2339,6 +2473,50 @@ static void RenderSSPOptions(const ToolChain &TC, const ArgList &Args,
}
}
+static void RenderTrivialAutoVarInitOptions(const Driver &D,
+ const ToolChain &TC,
+ const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ auto DefaultTrivialAutoVarInit = TC.GetDefaultTrivialAutoVarInit();
+ StringRef TrivialAutoVarInit = "";
+
+ for (const Arg *A : Args) {
+ switch (A->getOption().getID()) {
+ default:
+ continue;
+ case options::OPT_ftrivial_auto_var_init: {
+ A->claim();
+ StringRef Val = A->getValue();
+ if (Val == "uninitialized" || Val == "zero" || Val == "pattern")
+ TrivialAutoVarInit = Val;
+ else
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Val;
+ break;
+ }
+ }
+ }
+
+ if (TrivialAutoVarInit.empty())
+ switch (DefaultTrivialAutoVarInit) {
+ case LangOptions::TrivialAutoVarInitKind::Uninitialized:
+ break;
+ case LangOptions::TrivialAutoVarInitKind::Pattern:
+ TrivialAutoVarInit = "pattern";
+ break;
+ case LangOptions::TrivialAutoVarInitKind::Zero:
+ TrivialAutoVarInit = "zero";
+ break;
+ }
+
+ if (!TrivialAutoVarInit.empty()) {
+ if (TrivialAutoVarInit == "zero" && !Args.hasArg(options::OPT_enable_trivial_var_init_zero))
+ D.Diag(diag::err_drv_trivial_auto_var_init_zero_disabled);
+ CmdArgs.push_back(
+ Args.MakeArgString("-ftrivial-auto-var-init=" + TrivialAutoVarInit));
+ }
+}
+
static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs) {
const unsigned ForwardedArguments[] = {
options::OPT_cl_opt_disable,
@@ -2658,8 +2836,10 @@ static void RenderCharacterOptions(const ArgList &Args, const llvm::Triple &T,
CmdArgs.push_back("-fno-signed-char");
}
- if (Args.hasFlag(options::OPT_fchar8__t, options::OPT_fno_char8__t, false))
- CmdArgs.push_back("-fchar8_t");
+ // The default depends on the language standard.
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_fchar8__t, options::OPT_fno_char8__t))
+ A->render(Args, CmdArgs);
if (const Arg *A = Args.getLastArg(options::OPT_fshort_wchar,
options::OPT_fno_short_wchar)) {
@@ -2669,8 +2849,8 @@ static void RenderCharacterOptions(const ArgList &Args, const llvm::Triple &T,
} else {
bool IsARM = T.isARM() || T.isThumb() || T.isAArch64();
CmdArgs.push_back("-fwchar-type=int");
- if (IsARM && !(T.isOSWindows() || T.getOS() == llvm::Triple::NetBSD ||
- T.getOS() == llvm::Triple::OpenBSD))
+ if (IsARM && !(T.isOSWindows() || T.isOSNetBSD() ||
+ T.isOSOpenBSD()))
CmdArgs.push_back("-fno-signed-wchar");
else
CmdArgs.push_back("-fsigned-wchar");
@@ -2701,7 +2881,6 @@ static void RenderObjCOptions(const ToolChain &TC, const Driver &D,
// When ObjectiveC legacy runtime is in effect on MacOSX, turn on the option
// to do Array/Dictionary subscripting by default.
if (Arch == llvm::Triple::x86 && T.isMacOSX() &&
- !T.isMacOSXVersionLT(10, 7) &&
Runtime.getKind() == ObjCRuntime::FragileMacOSX && Runtime.isNeXTFamily())
CmdArgs.push_back("-fobjc-subscripting-legacy-runtime");
@@ -2737,6 +2916,18 @@ static void RenderObjCOptions(const ToolChain &TC, const Driver &D,
Args.ClaimAllArgs(options::OPT_fno_objc_arc_exceptions);
}
+ // Allow the user to control whether messages can be converted to runtime
+ // functions.
+ if (types::isObjC(Input.getType())) {
+ auto *Arg = Args.getLastArg(
+ options::OPT_fobjc_convert_messages_to_runtime_calls,
+ options::OPT_fno_objc_convert_messages_to_runtime_calls);
+ if (Arg &&
+ Arg->getOption().matches(
+ options::OPT_fno_objc_convert_messages_to_runtime_calls))
+ CmdArgs.push_back("-fno-objc-convert-messages-to-runtime-calls");
+ }
+
// -fobjc-infer-related-result-type is the default, except in the Objective-C
// rewriter.
if (InferCovariantReturns)
@@ -2872,12 +3063,35 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
CmdArgs.push_back("-fno-spell-checking");
}
+enum class DwarfFissionKind { None, Split, Single };
+
+static DwarfFissionKind getDebugFissionKind(const Driver &D,
+ const ArgList &Args, Arg *&Arg) {
+ Arg =
+ Args.getLastArg(options::OPT_gsplit_dwarf, options::OPT_gsplit_dwarf_EQ);
+ if (!Arg)
+ return DwarfFissionKind::None;
+
+ if (Arg->getOption().matches(options::OPT_gsplit_dwarf))
+ return DwarfFissionKind::Split;
+
+ StringRef Value = Arg->getValue();
+ if (Value == "split")
+ return DwarfFissionKind::Split;
+ if (Value == "single")
+ return DwarfFissionKind::Single;
+
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << Arg->getOption().getName() << Arg->getValue();
+ return DwarfFissionKind::None;
+}
+
static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
const llvm::Triple &T, const ArgList &Args,
bool EmitCodeView, bool IsWindowsMSVC,
ArgStringList &CmdArgs,
codegenoptions::DebugInfoKind &DebugInfoKind,
- const Arg *&SplitDWARFArg) {
+ DwarfFissionKind &DwarfFission) {
if (Args.hasFlag(options::OPT_fdebug_info_for_profiling,
options::OPT_fno_debug_info_for_profiling, false) &&
checkDebugInfoOption(
@@ -2902,10 +3116,12 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
Args.ClaimAllArgs(options::OPT_g_Group);
- SplitDWARFArg = Args.getLastArg(options::OPT_gsplit_dwarf);
+ Arg* SplitDWARFArg;
+ DwarfFission = getDebugFissionKind(D, Args, SplitDWARFArg);
- if (SplitDWARFArg && !checkDebugInfoOption(SplitDWARFArg, Args, D, TC)) {
- SplitDWARFArg = nullptr;
+ if (DwarfFission != DwarfFissionKind::None &&
+ !checkDebugInfoOption(SplitDWARFArg, Args, D, TC)) {
+ DwarfFission = DwarfFissionKind::None;
SplitDWARFInlining = false;
}
@@ -2922,12 +3138,13 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
// composing split-dwarf and line-tables-only, so let those compose
// naturally in that case. And if you just turned off debug info,
// (-gsplit-dwarf -g0) - do that.
- if (SplitDWARFArg) {
+ if (DwarfFission != DwarfFissionKind::None) {
if (A->getIndex() > SplitDWARFArg->getIndex()) {
if (DebugInfoKind == codegenoptions::NoDebugInfo ||
+ DebugInfoKind == codegenoptions::DebugDirectivesOnly ||
(DebugInfoKind == codegenoptions::DebugLineTablesOnly &&
SplitDWARFInlining))
- SplitDWARFArg = nullptr;
+ DwarfFission = DwarfFissionKind::None;
} else if (SplitDWARFInlining)
DebugInfoKind = codegenoptions::NoDebugInfo;
}
@@ -2960,21 +3177,28 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
if (checkDebugInfoOption(A, Args, D, TC))
DWARFVersion = DwarfVersionNum(A->getSpelling());
- // Forward -gcodeview. EmitCodeView might have been set by CL-compatibility
- // argument parsing.
- if (EmitCodeView) {
- if (const Arg *A = Args.getLastArg(options::OPT_gcodeview)) {
- EmitCodeView = checkDebugInfoOption(A, Args, D, TC);
- if (EmitCodeView) {
- // DWARFVersion remains at 0 if no explicit choice was made.
- CmdArgs.push_back("-gcodeview");
- }
- }
+ if (const Arg *A = Args.getLastArg(options::OPT_gcodeview)) {
+ if (checkDebugInfoOption(A, Args, D, TC))
+ EmitCodeView = true;
}
+ // 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 &&
- DebugInfoKind != codegenoptions::NoDebugInfo)
- DWARFVersion = TC.GetDefaultDwarfVersion();
+ DebugInfoKind != codegenoptions::NoDebugInfo) {
+ switch (TC.getDefaultDebugFormat()) {
+ case codegenoptions::DIF_CodeView:
+ EmitCodeView = true;
+ break;
+ case codegenoptions::DIF_DWARF:
+ DWARFVersion = TC.GetDefaultDwarfVersion();
+ break;
+ }
+ }
+
+ // -gline-directives-only supported only for the DWARF debug info.
+ if (DWARFVersion == 0 && DebugInfoKind == codegenoptions::DebugDirectivesOnly)
+ DebugInfoKind = codegenoptions::NoDebugInfo;
// We ignore flag -gstrict-dwarf for now.
// And we handle flag -grecord-gcc-switches later with DWARFDebugFlags.
@@ -2993,10 +3217,11 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
CmdArgs.push_back("-dwarf-column-info");
// FIXME: Move backend command line options to the module.
- // If -gline-tables-only is the last option it wins.
+ // If -gline-tables-only or -gline-directives-only is the last option it wins.
if (const Arg *A = Args.getLastArg(options::OPT_gmodules))
if (checkDebugInfoOption(A, Args, D, TC)) {
- if (DebugInfoKind != codegenoptions::DebugLineTablesOnly) {
+ if (DebugInfoKind != codegenoptions::DebugLineTablesOnly &&
+ DebugInfoKind != codegenoptions::DebugDirectivesOnly) {
DebugInfoKind = codegenoptions::LimitedDebugInfo;
CmdArgs.push_back("-dwarf-ext-refs");
CmdArgs.push_back("-fmodule-format=obj");
@@ -3005,15 +3230,19 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
// -gsplit-dwarf should turn on -g and enable the backend dwarf
// splitting and extraction.
- // FIXME: Currently only works on Linux.
- if (T.isOSLinux()) {
+ // FIXME: Currently only works on Linux and Fuchsia.
+ if (T.isOSLinux() || T.isOSFuchsia()) {
if (!SplitDWARFInlining)
CmdArgs.push_back("-fno-split-dwarf-inlining");
- if (SplitDWARFArg) {
+ if (DwarfFission != DwarfFissionKind::None) {
if (DebugInfoKind == codegenoptions::NoDebugInfo)
DebugInfoKind = codegenoptions::LimitedDebugInfo;
- CmdArgs.push_back("-enable-split-dwarf");
+
+ if (DwarfFission == DwarfFissionKind::Single)
+ CmdArgs.push_back("-enable-split-dwarf=single");
+ else
+ CmdArgs.push_back("-enable-split-dwarf");
}
}
@@ -3044,6 +3273,19 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
CmdArgs.push_back("-gembed-source");
}
+ if (EmitCodeView) {
+ CmdArgs.push_back("-gcodeview");
+
+ // Emit codeview type hashes if requested.
+ if (Args.hasFlag(options::OPT_gcodeview_ghash,
+ options::OPT_gno_codeview_ghash, false)) {
+ CmdArgs.push_back("-gcodeview-ghash");
+ }
+ }
+
+ // Adjust the debug info kind for the given toolchain.
+ TC.adjustDebugInfoKind(DebugInfoKind, Args);
+
RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, DWARFVersion,
DebuggerTuning);
@@ -3055,11 +3297,24 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
CmdArgs.push_back("-debug-info-macro");
// -ggnu-pubnames turns on gnu style pubnames in the backend.
- if (Args.hasFlag(options::OPT_ggnu_pubnames, options::OPT_gno_gnu_pubnames,
- false))
- if (checkDebugInfoOption(Args.getLastArg(options::OPT_ggnu_pubnames), Args,
- D, TC))
- CmdArgs.push_back("-ggnu-pubnames");
+ const auto *PubnamesArg =
+ Args.getLastArg(options::OPT_ggnu_pubnames, options::OPT_gno_gnu_pubnames,
+ options::OPT_gpubnames, options::OPT_gno_pubnames);
+ if (DwarfFission != DwarfFissionKind::None ||
+ DebuggerTuning == llvm::DebuggerKind::LLDB ||
+ (PubnamesArg && checkDebugInfoOption(PubnamesArg, Args, D, TC)))
+ if (!PubnamesArg ||
+ (!PubnamesArg->getOption().matches(options::OPT_gno_gnu_pubnames) &&
+ !PubnamesArg->getOption().matches(options::OPT_gno_pubnames)))
+ CmdArgs.push_back(PubnamesArg && PubnamesArg->getOption().matches(
+ options::OPT_gpubnames)
+ ? "-gpubnames"
+ : "-ggnu-pubnames");
+
+ if (Args.hasFlag(options::OPT_fdebug_ranges_base_address,
+ options::OPT_fno_debug_ranges_base_address, false)) {
+ CmdArgs.push_back("-fdebug-ranges-base-address");
+ }
// -gdwarf-aranges turns on the emission of the aranges section in the
// backend.
@@ -3103,32 +3358,64 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const ArgList &Args, const char *LinkingOutput) const {
- const llvm::Triple &RawTriple = getToolChain().getTriple();
- const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
+ const auto &TC = getToolChain();
+ const llvm::Triple &RawTriple = TC.getTriple();
+ const llvm::Triple &Triple = TC.getEffectiveTriple();
const std::string &TripleStr = Triple.getTriple();
bool KernelOrKext =
Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
- const Driver &D = getToolChain().getDriver();
+ const Driver &D = TC.getDriver();
ArgStringList CmdArgs;
// Check number of inputs for sanity. We need at least one input.
assert(Inputs.size() >= 1 && "Must have at least one input.");
- const InputInfo &Input = Inputs[0];
// CUDA/HIP compilation may have multiple inputs (source file + results of
// device-side compilations). OpenMP device jobs also take the host IR as a
- // second input. All other jobs are expected to have exactly one
- // input.
+ // second input. Module precompilation accepts a list of header files to
+ // include as part of the module. All other jobs are expected to have exactly
+ // one input.
bool IsCuda = JA.isOffloading(Action::OFK_Cuda);
bool IsHIP = JA.isOffloading(Action::OFK_HIP);
bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP);
- assert((IsCuda || IsHIP || (IsOpenMPDevice && Inputs.size() == 2) ||
- Inputs.size() == 1) &&
- "Unable to handle multiple inputs.");
-
- const llvm::Triple *AuxTriple =
- IsCuda ? getToolChain().getAuxTriple() : nullptr;
+ bool IsHeaderModulePrecompile = isa<HeaderModulePrecompileJobAction>(JA);
+
+ // A header module compilation doesn't have a main input file, so invent a
+ // fake one as a placeholder.
+ const char *ModuleName = [&]{
+ auto *ModuleNameArg = Args.getLastArg(options::OPT_fmodule_name_EQ);
+ return ModuleNameArg ? ModuleNameArg->getValue() : "";
+ }();
+ InputInfo HeaderModuleInput(Inputs[0].getType(), ModuleName, ModuleName);
+
+ const InputInfo &Input =
+ IsHeaderModulePrecompile ? HeaderModuleInput : Inputs[0];
+
+ InputInfoList ModuleHeaderInputs;
+ const InputInfo *CudaDeviceInput = nullptr;
+ const InputInfo *OpenMPDeviceInput = nullptr;
+ for (const InputInfo &I : Inputs) {
+ if (&I == &Input) {
+ // This is the primary input.
+ } else if (IsHeaderModulePrecompile &&
+ types::getPrecompiledType(I.getType()) == types::TY_PCH) {
+ types::ID Expected = HeaderModuleInput.getType();
+ if (I.getType() != Expected) {
+ D.Diag(diag::err_drv_module_header_wrong_kind)
+ << I.getFilename() << types::getTypeName(I.getType())
+ << types::getTypeName(Expected);
+ }
+ ModuleHeaderInputs.push_back(I);
+ } else if ((IsCuda || IsHIP) && !CudaDeviceInput) {
+ CudaDeviceInput = &I;
+ } else if (IsOpenMPDevice && !OpenMPDeviceInput) {
+ OpenMPDeviceInput = &I;
+ } else {
+ llvm_unreachable("unexpectedly given multiple inputs");
+ }
+ }
+ const llvm::Triple *AuxTriple = IsCuda ? TC.getAuxTriple() : nullptr;
bool IsWindowsGNU = RawTriple.isWindowsGNUEnvironment();
bool IsWindowsCygnus = RawTriple.isWindowsCygwinEnvironment();
bool IsWindowsMSVC = RawTriple.isWindowsMSVCEnvironment();
@@ -3204,7 +3491,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Push all default warning arguments that are specific to
// the given target. These come before user provided warning options
// are provided.
- getToolChain().addClangWarningOptions(CmdArgs);
+ TC.addClangWarningOptions(CmdArgs);
// Select the appropriate action.
RewriteKind rewriteKind = RK_None;
@@ -3231,17 +3518,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Also ignore explicit -force_cpusubtype_ALL option.
(void)Args.hasArg(options::OPT_force__cpusubtype__ALL);
} else if (isa<PrecompileJobAction>(JA)) {
- // Use PCH if the user requested it.
- bool UsePCH = D.CCCUsePCH;
-
if (JA.getType() == types::TY_Nothing)
CmdArgs.push_back("-fsyntax-only");
else if (JA.getType() == types::TY_ModuleFile)
- CmdArgs.push_back("-emit-module-interface");
- else if (UsePCH)
- CmdArgs.push_back("-emit-pch");
+ CmdArgs.push_back(IsHeaderModulePrecompile
+ ? "-emit-header-module"
+ : "-emit-module-interface");
else
- CmdArgs.push_back("-emit-pth");
+ CmdArgs.push_back("-emit-pch");
} else if (isa<VerifyPCHJobAction>(JA)) {
CmdArgs.push_back("-verify-pch");
} else {
@@ -3305,13 +3589,116 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_save_temps_EQ);
// Embed-bitcode option.
+ // Only white-listed flags below are allowed to be embedded.
if (C.getDriver().embedBitcodeInObject() && !C.getDriver().isUsingLTO() &&
(isa<BackendJobAction>(JA) || isa<AssembleJobAction>(JA))) {
// Add flags implied by -fembed-bitcode.
Args.AddLastArg(CmdArgs, options::OPT_fembed_bitcode_EQ);
// Disable all llvm IR level optimizations.
CmdArgs.push_back("-disable-llvm-passes");
+
+ // reject options that shouldn't be supported in bitcode
+ // also reject kernel/kext
+ static const constexpr unsigned kBitcodeOptionBlacklist[] = {
+ options::OPT_mkernel,
+ options::OPT_fapple_kext,
+ options::OPT_ffunction_sections,
+ options::OPT_fno_function_sections,
+ options::OPT_fdata_sections,
+ options::OPT_fno_data_sections,
+ options::OPT_funique_section_names,
+ options::OPT_fno_unique_section_names,
+ options::OPT_mrestrict_it,
+ options::OPT_mno_restrict_it,
+ options::OPT_mstackrealign,
+ options::OPT_mno_stackrealign,
+ options::OPT_mstack_alignment,
+ options::OPT_mcmodel_EQ,
+ options::OPT_mlong_calls,
+ options::OPT_mno_long_calls,
+ options::OPT_ggnu_pubnames,
+ options::OPT_gdwarf_aranges,
+ options::OPT_fdebug_types_section,
+ options::OPT_fno_debug_types_section,
+ options::OPT_fdwarf_directory_asm,
+ options::OPT_fno_dwarf_directory_asm,
+ options::OPT_mrelax_all,
+ options::OPT_mno_relax_all,
+ options::OPT_ftrap_function_EQ,
+ options::OPT_ffixed_r9,
+ options::OPT_mfix_cortex_a53_835769,
+ options::OPT_mno_fix_cortex_a53_835769,
+ options::OPT_ffixed_x18,
+ options::OPT_mglobal_merge,
+ options::OPT_mno_global_merge,
+ options::OPT_mred_zone,
+ options::OPT_mno_red_zone,
+ options::OPT_Wa_COMMA,
+ options::OPT_Xassembler,
+ options::OPT_mllvm,
+ };
+ for (const auto &A : Args)
+ if (std::find(std::begin(kBitcodeOptionBlacklist),
+ std::end(kBitcodeOptionBlacklist),
+ A->getOption().getID()) !=
+ std::end(kBitcodeOptionBlacklist))
+ D.Diag(diag::err_drv_unsupported_embed_bitcode) << A->getSpelling();
+
+ // Render the CodeGen options that need to be passed.
+ if (!Args.hasFlag(options::OPT_foptimize_sibling_calls,
+ options::OPT_fno_optimize_sibling_calls))
+ CmdArgs.push_back("-mdisable-tail-calls");
+
+ RenderFloatingPointOptions(TC, D, isOptimizationLevelFast(Args), Args,
+ CmdArgs);
+
+ // Render ABI arguments
+ switch (TC.getArch()) {
+ default: break;
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumbeb:
+ RenderARMABI(Triple, Args, CmdArgs);
+ break;
+ case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_be:
+ RenderAArch64ABI(Triple, Args, CmdArgs);
+ break;
+ }
+
+ // Optimization level for CodeGen.
+ if (const Arg *A = Args.getLastArg(options::OPT_O_Group)) {
+ if (A->getOption().matches(options::OPT_O4)) {
+ CmdArgs.push_back("-O3");
+ D.Diag(diag::warn_O4_is_O3);
+ } else {
+ A->render(Args, CmdArgs);
+ }
+ }
+
+ // Input/Output file.
+ if (Output.getType() == types::TY_Dependencies) {
+ // Handled with other dependency code.
+ } else if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Input output.");
+ }
+
+ for (const auto &II : Inputs) {
+ addDashXForInput(Args, II, CmdArgs);
+ if (II.isFilename())
+ CmdArgs.push_back(II.getFilename());
+ else
+ II.getInputArg().renderAsInput(Args, CmdArgs);
+ }
+
+ C.addCommand(llvm::make_unique<Command>(JA, *this, D.getClangProgramPath(),
+ CmdArgs, Inputs));
+ return;
}
+
if (C.getDriver().embedBitcodeMarkerOnly() && !C.getDriver().isUsingLTO())
CmdArgs.push_back("-fembed-bitcode=marker");
@@ -3346,12 +3733,33 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_static))
CmdArgs.push_back("-static-define");
+ if (Args.hasArg(options::OPT_municode))
+ CmdArgs.push_back("-DUNICODE");
+
if (isa<AnalyzeJobAction>(JA))
RenderAnalyzerOptions(Args, CmdArgs, Triple, Input);
+ // Enable compatilibily mode to avoid analyzer-config related errors.
+ // Since we can't access frontend flags through hasArg, let's manually iterate
+ // through them.
+ bool FoundAnalyzerConfig = false;
+ for (auto Arg : Args.filtered(options::OPT_Xclang))
+ if (StringRef(Arg->getValue()) == "-analyzer-config") {
+ FoundAnalyzerConfig = true;
+ break;
+ }
+ if (!FoundAnalyzerConfig)
+ for (auto Arg : Args.filtered(options::OPT_Xanalyzer))
+ if (StringRef(Arg->getValue()) == "-analyzer-config") {
+ FoundAnalyzerConfig = true;
+ break;
+ }
+ if (FoundAnalyzerConfig)
+ CmdArgs.push_back("-analyzer-config-compatibility-mode=true");
+
CheckCodeGenerationOptions(D, Args);
- unsigned FunctionAlignment = ParseFunctionAlignment(getToolChain(), Args);
+ unsigned FunctionAlignment = ParseFunctionAlignment(TC, Args);
assert(FunctionAlignment <= 31 && "function alignment will be truncated!");
if (FunctionAlignment) {
CmdArgs.push_back("-function-alignment");
@@ -3361,8 +3769,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
llvm::Reloc::Model RelocationModel;
unsigned PICLevel;
bool IsPIE;
- std::tie(RelocationModel, PICLevel, IsPIE) =
- ParsePICArgs(getToolChain(), Args);
+ std::tie(RelocationModel, PICLevel, IsPIE) = ParsePICArgs(TC, Args);
const char *RMName = RelocationModelName(RelocationModel);
@@ -3390,13 +3797,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-mthread-model");
if (Arg *A = Args.getLastArg(options::OPT_mthread_model)) {
- if (!getToolChain().isThreadModelSupported(A->getValue()))
+ if (!TC.isThreadModelSupported(A->getValue()))
D.Diag(diag::err_drv_invalid_thread_model_for_target)
<< A->getValue() << A->getAsString(Args);
CmdArgs.push_back(A->getValue());
}
else
- CmdArgs.push_back(Args.MakeArgString(getToolChain().getThreadModel()));
+ CmdArgs.push_back(Args.MakeArgString(TC.getThreadModel()));
Args.AddLastArg(CmdArgs, options::OPT_fveclib);
@@ -3451,7 +3858,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Arg *A = Args.getLastArg(options::OPT_fpcc_struct_return,
options::OPT_freg_struct_return)) {
- if (getToolChain().getArch() != llvm::Triple::x86) {
+ if (TC.getArch() != llvm::Triple::x86) {
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getSpelling() << RawTriple.str();
} else if (A->getOption().matches(options::OPT_fpcc_struct_return)) {
@@ -3516,18 +3923,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_fsplit_stack))
CmdArgs.push_back("-split-stacks");
- RenderFloatingPointOptions(getToolChain(), D, OFastEnabled, Args, CmdArgs);
+ RenderFloatingPointOptions(TC, D, OFastEnabled, Args, CmdArgs);
// Decide whether to use verbose asm. Verbose assembly is the default on
// toolchains which have the integrated assembler on by default.
- bool IsIntegratedAssemblerDefault =
- getToolChain().IsIntegratedAssemblerDefault();
+ bool IsIntegratedAssemblerDefault = TC.IsIntegratedAssemblerDefault();
if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,
IsIntegratedAssemblerDefault) ||
Args.hasArg(options::OPT_dA))
CmdArgs.push_back("-masm-verbose");
- if (!getToolChain().useIntegratedAs())
+ if (!TC.useIntegratedAs())
CmdArgs.push_back("-no-integrated-as");
if (Args.hasArg(options::OPT_fdebug_pass_structure)) {
@@ -3580,20 +3986,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
bool AsynchronousUnwindTables =
Args.hasFlag(options::OPT_fasynchronous_unwind_tables,
options::OPT_fno_asynchronous_unwind_tables,
- (getToolChain().IsUnwindTablesDefault(Args) ||
- getToolChain().getSanitizerArgs().needsUnwindTables()) &&
+ (TC.IsUnwindTablesDefault(Args) ||
+ TC.getSanitizerArgs().needsUnwindTables()) &&
!Freestanding);
if (Args.hasFlag(options::OPT_funwind_tables, options::OPT_fno_unwind_tables,
AsynchronousUnwindTables))
CmdArgs.push_back("-munwind-tables");
- getToolChain().addClangTargetOptions(Args, CmdArgs,
- JA.getOffloadingDeviceKind());
-
- if (Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
- CmdArgs.push_back("-mlimit-float-precision");
- CmdArgs.push_back(A->getValue());
- }
+ TC.addClangTargetOptions(Args, CmdArgs, JA.getOffloadingDeviceKind());
// FIXME: Handle -mtune=.
(void)Args.hasArg(options::OPT_mtune_EQ);
@@ -3620,22 +4020,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
types::ID InputType = Input.getType();
if (D.IsCLMode())
AddClangCLArgs(Args, InputType, CmdArgs, &DebugInfoKind, &EmitCodeView);
- else
- EmitCodeView = Args.hasArg(options::OPT_gcodeview);
- const Arg *SplitDWARFArg = nullptr;
- RenderDebugOptions(getToolChain(), D, RawTriple, Args, EmitCodeView,
- IsWindowsMSVC, CmdArgs, DebugInfoKind, SplitDWARFArg);
+ DwarfFissionKind DwarfFission;
+ RenderDebugOptions(TC, D, RawTriple, Args, EmitCodeView, IsWindowsMSVC,
+ CmdArgs, DebugInfoKind, DwarfFission);
// Add the split debug info name to the command lines here so we
// can propagate it to the backend.
- bool SplitDWARF = SplitDWARFArg && RawTriple.isOSLinux() &&
+ bool SplitDWARF = (DwarfFission != DwarfFissionKind::None) &&
+ (RawTriple.isOSLinux() || RawTriple.isOSFuchsia()) &&
(isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA) ||
isa<BackendJobAction>(JA));
const char *SplitDWARFOut;
if (SplitDWARF) {
CmdArgs.push_back("-split-dwarf-file");
- SplitDWARFOut = SplitDebugName(Args, Input);
+ SplitDWARFOut = SplitDebugName(Args, Output);
CmdArgs.push_back(SplitDWARFOut);
}
@@ -3653,7 +4052,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_fallow_unsupported)) {
Arg *Unsupported;
if (types::isCXX(InputType) && RawTriple.isOSDarwin() &&
- getToolChain().getArch() == llvm::Triple::x86) {
+ TC.getArch() == llvm::Triple::x86) {
if ((Unsupported = Args.getLastArg(options::OPT_fapple_kext)) ||
(Unsupported = Args.getLastArg(options::OPT_mkernel)))
D.Diag(diag::err_drv_clang_unsupported_opt_cxx_darwin_i386)
@@ -3717,9 +4116,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
ABICompatArg->render(Args, CmdArgs);
// Add runtime flag for PS4 when PGO, coverage, or sanitizers are enabled.
- if (RawTriple.isPS4CPU()) {
- PS4cpu::addProfileRTArgs(getToolChain(), Args, CmdArgs);
- PS4cpu::addSanitizerArgs(getToolChain(), CmdArgs);
+ if (RawTriple.isPS4CPU() &&
+ !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ PS4cpu::addProfileRTArgs(TC, Args, CmdArgs);
+ PS4cpu::addSanitizerArgs(TC, CmdArgs);
}
// Pass options for controlling the default header search paths.
@@ -3867,10 +4267,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fno-gnu-keywords");
}
- if (ShouldDisableDwarfDirectory(Args, getToolChain()))
+ if (ShouldDisableDwarfDirectory(Args, TC))
CmdArgs.push_back("-fno-dwarf-directory-asm");
- if (ShouldDisableAutolink(Args, getToolChain()))
+ if (ShouldDisableAutolink(Args, TC))
CmdArgs.push_back("-fno-autolink");
// Add in -fdebug-compilation-dir if necessary.
@@ -3916,6 +4316,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_relocatable_pch))
CmdArgs.push_back("-relocatable-pch");
+ if (const Arg *A = Args.getLastArg(options::OPT_fcf_runtime_abi_EQ)) {
+ static const char *kCFABIs[] = {
+ "standalone", "objc", "swift", "swift-5.0", "swift-4.2", "swift-4.1",
+ };
+
+ if (find(kCFABIs, StringRef(A->getValue())) == std::end(kCFABIs))
+ D.Diag(diag::err_drv_invalid_cf_runtime_abi) << A->getValue();
+ else
+ A->render(Args, CmdArgs);
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_fconstant_string_class_EQ)) {
CmdArgs.push_back("-fconstant-string-class");
CmdArgs.push_back(A->getValue());
@@ -3983,6 +4394,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden);
+ Args.AddLastArg(CmdArgs, options::OPT_fvisibility_global_new_delete_hidden);
Args.AddLastArg(CmdArgs, options::OPT_ftlsmodel_EQ);
@@ -3993,6 +4405,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);
Args.AddLastArg(CmdArgs, options::OPT_femulated_tls,
options::OPT_fno_emulated_tls);
+ Args.AddLastArg(CmdArgs, options::OPT_fkeep_static_consts);
// AltiVec-like language extensions aren't relevant for assembling.
if (!isa<PreprocessJobAction>(JA) || Output.getType() != types::TY_PP_Asm)
@@ -4022,11 +4435,25 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fopenmp_simd,
options::OPT_fno_openmp_simd);
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ);
+ Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_cuda_number_of_sm_EQ);
+ Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_cuda_blocks_per_sm_EQ);
+ if (Args.hasFlag(options::OPT_fopenmp_optimistic_collapse,
+ options::OPT_fno_openmp_optimistic_collapse,
+ /*Default=*/false))
+ CmdArgs.push_back("-fopenmp-optimistic-collapse");
// When in OpenMP offloading mode with NVPTX target, forward
// cuda-mode flag
- Args.AddLastArg(CmdArgs, options::OPT_fopenmp_cuda_mode,
- options::OPT_fno_openmp_cuda_mode);
+ if (Args.hasFlag(options::OPT_fopenmp_cuda_mode,
+ options::OPT_fno_openmp_cuda_mode, /*Default=*/false))
+ CmdArgs.push_back("-fopenmp-cuda-mode");
+
+ // When in OpenMP offloading mode with NVPTX target, check if full runtime
+ // is required.
+ if (Args.hasFlag(options::OPT_fopenmp_cuda_force_full_runtime,
+ options::OPT_fno_openmp_cuda_force_full_runtime,
+ /*Default=*/false))
+ CmdArgs.push_back("-fopenmp-cuda-force-full-runtime");
break;
default:
// By default, if Clang doesn't know how to generate useful OpenMP code
@@ -4043,16 +4470,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ);
}
- const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs();
- Sanitize.addArgs(getToolChain(), Args, CmdArgs, InputType);
+ const SanitizerArgs &Sanitize = TC.getSanitizerArgs();
+ Sanitize.addArgs(TC, Args, CmdArgs, InputType);
- const XRayArgs &XRay = getToolChain().getXRayArgs();
- XRay.addArgs(getToolChain(), Args, CmdArgs, InputType);
+ const XRayArgs &XRay = TC.getXRayArgs();
+ XRay.addArgs(TC, Args, CmdArgs, InputType);
- if (getToolChain().SupportsProfiling())
+ if (TC.SupportsProfiling())
Args.AddLastArg(CmdArgs, options::OPT_pg);
- if (getToolChain().SupportsProfiling())
+ if (TC.SupportsProfiling())
Args.AddLastArg(CmdArgs, options::OPT_mfentry);
// -flax-vector-conversions is default.
@@ -4099,7 +4526,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_pthread);
- RenderSSPOptions(getToolChain(), Args, CmdArgs, KernelOrKext);
+ if (Args.hasFlag(options::OPT_mspeculative_load_hardening, options::OPT_mno_speculative_load_hardening,
+ false))
+ CmdArgs.push_back(Args.MakeArgString("-mspeculative-load-hardening"));
+
+ RenderSSPOptions(TC, Args, CmdArgs, KernelOrKext);
+ RenderTrivialAutoVarInitOptions(D, TC, Args, CmdArgs);
// Translate -mstackrealign
if (Args.hasFlag(options::OPT_mstackrealign, options::OPT_mno_stackrealign,
@@ -4158,8 +4590,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
else
A->render(Args, CmdArgs);
}
+ Args.AddLastArg(CmdArgs, options::OPT_fprofile_remapping_file_EQ);
- RenderBuiltinOptions(getToolChain(), RawTriple, Args, CmdArgs);
+ RenderBuiltinOptions(TC, RawTriple, Args, CmdArgs);
if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
options::OPT_fno_assume_sane_operator_new))
@@ -4167,19 +4600,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fblocks=0 is default.
if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks,
- getToolChain().IsBlocksDefault()) ||
+ TC.IsBlocksDefault()) ||
(Args.hasArg(options::OPT_fgnu_runtime) &&
Args.hasArg(options::OPT_fobjc_nonfragile_abi) &&
!Args.hasArg(options::OPT_fno_blocks))) {
CmdArgs.push_back("-fblocks");
- if (!Args.hasArg(options::OPT_fgnu_runtime) &&
- !getToolChain().hasBlocksRuntime())
+ if (!Args.hasArg(options::OPT_fgnu_runtime) && !TC.hasBlocksRuntime())
CmdArgs.push_back("-fblocks-runtime-optional");
}
// -fencode-extended-block-signature=1 is default.
- if (getToolChain().IsEncodeExtendedBlockSignatureDefault())
+ if (TC.IsEncodeExtendedBlockSignatureDefault())
CmdArgs.push_back("-fencode-extended-block-signature");
if (Args.hasFlag(options::OPT_fcoroutines_ts, options::OPT_fno_coroutines_ts,
@@ -4204,7 +4636,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_felide_constructors, false))
CmdArgs.push_back("-fno-elide-constructors");
- ToolChain::RTTIMode RTTIMode = getToolChain().getRTTIMode();
+ ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
if (KernelOrKext || (types::isCXX(InputType) &&
(RTTIMode == ToolChain::RM_Disabled)))
@@ -4212,7 +4644,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fshort-enums=0 is default for all architectures except Hexagon.
if (Args.hasFlag(options::OPT_fshort_enums, options::OPT_fno_short_enums,
- getToolChain().getArch() == llvm::Triple::hexagon))
+ TC.getArch() == llvm::Triple::hexagon))
CmdArgs.push_back("-fshort-enums");
RenderCharacterOptions(Args, AuxTriple ? *AuxTriple : RawTriple, CmdArgs);
@@ -4222,8 +4654,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit,
!RawTriple.isOSWindows() &&
RawTriple.getOS() != llvm::Triple::Solaris &&
- getToolChain().getArch() != llvm::Triple::hexagon &&
- getToolChain().getArch() != llvm::Triple::xcore &&
+ TC.getArch() != llvm::Triple::xcore &&
((RawTriple.getVendor() != llvm::Triple::MipsTechnologies) ||
RawTriple.hasEnvironment())) ||
KernelOrKext)
@@ -4252,7 +4683,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_ms_extensions, true))))
CmdArgs.push_back("-fms-compatibility");
- VersionTuple MSVT = getToolChain().computeMSVCVersion(&D, Args);
+ VersionTuple MSVT = TC.computeMSVCVersion(&D, Args);
if (!MSVT.empty())
CmdArgs.push_back(
Args.MakeArgString("-fms-compatibility-version=" + MSVT.getAsString()));
@@ -4330,8 +4761,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_experimental_new_pass_manager);
ObjCRuntime Runtime = AddObjCRuntimeArgs(Args, CmdArgs, rewriteKind);
- RenderObjCOptions(getToolChain(), D, RawTriple, Args, Runtime,
- rewriteKind != RK_None, Input, CmdArgs);
+ RenderObjCOptions(TC, D, RawTriple, Args, Runtime, rewriteKind != RK_None,
+ Input, CmdArgs);
if (Args.hasFlag(options::OPT_fapplication_extension,
options::OPT_fno_application_extension, false))
@@ -4339,8 +4770,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Handle GCC-style exception args.
if (!C.getDriver().IsCLMode())
- addExceptionArgs(Args, InputType, getToolChain(), KernelOrKext, Runtime,
- CmdArgs);
+ addExceptionArgs(Args, InputType, TC, KernelOrKext, Runtime, CmdArgs);
// Handle exception personalities
Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions,
@@ -4355,7 +4785,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Opt.matches(options::OPT_fdwarf_exceptions))
CmdArgs.push_back("-fdwarf-exceptions");
} else {
- switch (getToolChain().GetExceptionModel(Args)) {
+ switch (TC.GetExceptionModel(Args)) {
default:
break;
case llvm::ExceptionHandling::DwarfCFI:
@@ -4592,7 +5022,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// nice to enable this when doing a crashdump for modules as well.
if (Args.hasFlag(options::OPT_frewrite_includes,
options::OPT_fno_rewrite_includes, false) ||
- (C.isForDiagnostics() && (RewriteImports || !HaveModules)))
+ (C.isForDiagnostics() && !HaveModules))
CmdArgs.push_back("-frewrite-includes");
// Only allow -traditional or -traditional-cpp outside in preprocessing modes.
@@ -4685,23 +5115,39 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
addDashXForInput(Args, Input, CmdArgs);
- if (Input.isFilename())
- CmdArgs.push_back(Input.getFilename());
- else
- Input.getInputArg().renderAsInput(Args, CmdArgs);
+ ArrayRef<InputInfo> FrontendInputs = Input;
+ if (IsHeaderModulePrecompile)
+ FrontendInputs = ModuleHeaderInputs;
+ else if (Input.isNothing())
+ FrontendInputs = {};
+
+ for (const InputInfo &Input : FrontendInputs) {
+ if (Input.isFilename())
+ CmdArgs.push_back(Input.getFilename());
+ else
+ Input.getInputArg().renderAsInput(Args, CmdArgs);
+ }
Args.AddAllArgs(CmdArgs, options::OPT_undef);
const char *Exec = D.getClangProgramPath();
- // Optionally embed the -cc1 level arguments into the debug info, for build
- // analysis.
+ // Optionally embed the -cc1 level arguments into the debug info or a
+ // section, for build analysis.
// Also record command line arguments into the debug info if
// -grecord-gcc-switches options is set on.
// By default, -gno-record-gcc-switches is set on and no recording.
- if (getToolChain().UseDwarfDebugFlags() ||
- Args.hasFlag(options::OPT_grecord_gcc_switches,
- options::OPT_gno_record_gcc_switches, false)) {
+ auto GRecordSwitches =
+ Args.hasFlag(options::OPT_grecord_command_line,
+ options::OPT_gno_record_command_line, false);
+ auto FRecordSwitches =
+ Args.hasFlag(options::OPT_frecord_command_line,
+ options::OPT_fno_record_command_line, false);
+ if (FRecordSwitches && !Triple.isOSBinFormatELF())
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << Args.getLastArg(options::OPT_frecord_command_line)->getAsString(Args)
+ << TripleStr;
+ if (TC.UseDwarfDebugFlags() || GRecordSwitches || FRecordSwitches) {
ArgStringList OriginalArgs;
for (const auto &Arg : Args)
Arg->render(Args, OriginalArgs);
@@ -4714,21 +5160,27 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Flags += " ";
Flags += EscapedArg;
}
- CmdArgs.push_back("-dwarf-debug-flags");
- CmdArgs.push_back(Args.MakeArgString(Flags));
+ auto FlagsArgString = Args.MakeArgString(Flags);
+ if (TC.UseDwarfDebugFlags() || GRecordSwitches) {
+ CmdArgs.push_back("-dwarf-debug-flags");
+ CmdArgs.push_back(FlagsArgString);
+ }
+ if (FRecordSwitches) {
+ CmdArgs.push_back("-record-command-line");
+ CmdArgs.push_back(FlagsArgString);
+ }
}
- if (IsCuda) {
- // Host-side cuda compilation receives all device-side outputs in a single
- // fatbin as Inputs[1]. Include the binary with -fcuda-include-gpubinary.
- if (Inputs.size() > 1) {
- assert(Inputs.size() == 2 && "More than one GPU binary!");
+ // Host-side cuda compilation receives all device-side outputs in a single
+ // fatbin as Inputs[1]. Include the binary with -fcuda-include-gpubinary.
+ if ((IsCuda || IsHIP) && CudaDeviceInput) {
CmdArgs.push_back("-fcuda-include-gpubinary");
- CmdArgs.push_back(Inputs[1].getFilename());
- }
+ CmdArgs.push_back(CudaDeviceInput->getFilename());
+ if (Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false))
+ CmdArgs.push_back("-fgpu-rdc");
+ }
- if (Args.hasFlag(options::OPT_fcuda_rdc, options::OPT_fno_cuda_rdc, false))
- CmdArgs.push_back("-fcuda-rdc");
+ if (IsCuda) {
if (Args.hasFlag(options::OPT_fcuda_short_ptr,
options::OPT_fno_cuda_short_ptr, false))
CmdArgs.push_back("-fcuda-short-ptr");
@@ -4741,9 +5193,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// only the relevant declarations are emitted.
if (IsOpenMPDevice) {
CmdArgs.push_back("-fopenmp-is-device");
- if (Inputs.size() == 2) {
+ if (OpenMPDeviceInput) {
CmdArgs.push_back("-fopenmp-host-ir-file-path");
- CmdArgs.push_back(Args.MakeArgString(Inputs.back().getFilename()));
+ CmdArgs.push_back(Args.MakeArgString(OpenMPDeviceInput->getFilename()));
}
}
@@ -4777,6 +5229,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fwhole-program-vtables");
}
+ bool RequiresSplitLTOUnit = WholeProgramVTables || Sanitize.needsLTO();
+ bool SplitLTOUnit =
+ Args.hasFlag(options::OPT_fsplit_lto_unit,
+ options::OPT_fno_split_lto_unit, RequiresSplitLTOUnit);
+ if (RequiresSplitLTOUnit && !SplitLTOUnit)
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << "-fno-split-lto-unit"
+ << (WholeProgramVTables ? "-fwhole-program-vtables" : "-fsanitize=cfi");
+ if (SplitLTOUnit)
+ CmdArgs.push_back("-fsplit-lto-unit");
+
if (Arg *A = Args.getLastArg(options::OPT_fexperimental_isel,
options::OPT_fno_experimental_isel)) {
CmdArgs.push_back("-mllvm");
@@ -4818,6 +5281,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_complete_member_pointers, false))
CmdArgs.push_back("-fcomplete-member-pointers");
+ if (!Args.hasFlag(options::OPT_fcxx_static_destructors,
+ options::OPT_fno_cxx_static_destructors, true))
+ CmdArgs.push_back("-fno-c++-static-destructors");
+
if (Arg *A = Args.getLastArg(options::OPT_moutline,
options::OPT_mno_outline)) {
if (A->getOption().matches(options::OPT_moutline)) {
@@ -4838,8 +5305,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
if (Args.hasFlag(options::OPT_faddrsig, options::OPT_fno_addrsig,
- getToolChain().getTriple().isOSBinFormatELF() &&
- getToolChain().useIntegratedAs()))
+ (TC.getTriple().isOSBinFormatELF() ||
+ TC.getTriple().isOSBinFormatCOFF()) &&
+ !TC.getTriple().isPS4() &&
+ !TC.getTriple().isOSNetBSD() &&
+ !Distro(D.getVFS()).IsGentoo() &&
+ !TC.getTriple().isAndroid() &&
+ TC.useIntegratedAs()))
CmdArgs.push_back("-faddrsig");
// Finally add the compile command to the compilation.
@@ -4860,16 +5332,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
+ // Make the compile command echo its inputs for /showFilenames.
+ if (Output.getType() == types::TY_Object &&
+ Args.hasFlag(options::OPT__SLASH_showFilenames,
+ options::OPT__SLASH_showFilenames_, false)) {
+ C.getJobs().getJobs().back()->setPrintInputFilenames(true);
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_pg))
- if (Args.hasArg(options::OPT_fomit_frame_pointer))
+ if (!shouldUseFramePointer(Args, Triple))
D.Diag(diag::err_drv_argument_not_allowed_with) << "-fomit-frame-pointer"
<< A->getAsString(Args);
// Claim some arguments which clang supports automatically.
// -fpch-preprocess is used with gcc to add a special marker in the output to
- // include the PCH file. Clang's PTH solution is completely transparent, so we
- // do not need to deal with it at all.
+ // include the PCH file.
Args.ClaimAllArgs(options::OPT_fpch_preprocess);
// Claim some arguments which clang doesn't support, but we don't
@@ -4912,7 +5390,8 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,
}
if ((runtime.getKind() == ObjCRuntime::GNUstep) &&
(runtime.getVersion() >= VersionTuple(2, 0)))
- if (!getToolChain().getTriple().isOSBinFormatELF()) {
+ if (!getToolChain().getTriple().isOSBinFormatELF() &&
+ !getToolChain().getTriple().isOSBinFormatCOFF()) {
getToolChain().getDriver().Diag(
diag::err_drv_gnustep_objc_runtime_incompatible_binary)
<< runtime.getVersion().getMajor();
@@ -5163,7 +5642,6 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
*DebugInfoKind = codegenoptions::LimitedDebugInfo;
else
*DebugInfoKind = codegenoptions::DebugLineTablesOnly;
- CmdArgs.push_back("-gcodeview");
} else {
*EmitCodeView = false;
}
@@ -5197,6 +5675,16 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
if (VolatileOptionID == options::OPT__SLASH_volatile_ms)
CmdArgs.push_back("-fms-volatile");
+ if (Args.hasFlag(options::OPT__SLASH_Zc_dllexportInlines_,
+ options::OPT__SLASH_Zc_dllexportInlines,
+ false)) {
+ if (Args.hasArg(options::OPT__SLASH_fallback)) {
+ D.Diag(clang::diag::err_drv_dllexport_inlines_and_fallback);
+ } else {
+ CmdArgs.push_back("-fno-dllexport-inlines");
+ }
+ }
+
Arg *MostGeneralArg = Args.getLastArg(options::OPT__SLASH_vmg);
Arg *BestCaseArg = Args.getLastArg(options::OPT__SLASH_vmb);
if (MostGeneralArg && BestCaseArg)
@@ -5270,9 +5758,28 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
CmdArgs.push_back("msvc");
}
- if (Args.hasArg(options::OPT__SLASH_Guard) &&
- Args.getLastArgValue(options::OPT__SLASH_Guard).equals_lower("cf"))
- CmdArgs.push_back("-cfguard");
+ 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)
+ CmdArgs.push_back("-cfguard");
+ }
}
visualstudio::Compiler *Clang::getCLFallback() const {
@@ -5525,10 +6032,12 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- if (Args.hasArg(options::OPT_gsplit_dwarf) &&
- getToolChain().getTriple().isOSLinux()) {
+ const llvm::Triple &T = getToolChain().getTriple();
+ Arg *A;
+ if ((getDebugFissionKind(D, Args, A) == DwarfFissionKind::Split) &&
+ (T.isOSLinux() || T.isOSFuchsia())) {
CmdArgs.push_back("-split-dwarf-file");
- CmdArgs.push_back(SplitDebugName(Args, Input));
+ CmdArgs.push_back(SplitDebugName(Args, Output));
}
assert(Input.isFilename() && "Invalid input.");
diff --git a/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp
index 1e093b25b909..d7e316befa61 100644
--- a/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/lib/Driver/ToolChains/CommonArgs.cpp
@@ -14,13 +14,13 @@
#include "Arch/PPC.h"
#include "Arch/SystemZ.h"
#include "Arch/X86.h"
+#include "HIP.h"
#include "Hexagon.h"
#include "InputInfo.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Version.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Config/config.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Compilation.h"
@@ -51,6 +51,7 @@
#include "llvm/Support/Program.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/TargetParser.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/YAMLParser.h"
using namespace clang::driver;
@@ -219,21 +220,6 @@ static std::string getR600TargetGPU(const ArgList &Args) {
return "";
}
-static std::string getNios2TargetCPU(const ArgList &Args) {
- Arg *A = Args.getLastArg(options::OPT_mcpu_EQ);
- if (!A)
- A = Args.getLastArg(options::OPT_march_EQ);
-
- if (!A)
- return "";
-
- const char *name = A->getValue();
- return llvm::StringSwitch<const char *>(name)
- .Case("r1", "nios2r1")
- .Case("r2", "nios2r2")
- .Default(name);
-}
-
static std::string getLanaiTargetCPU(const ArgList &Args) {
if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
return A->getValue();
@@ -270,7 +256,7 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T,
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
- return aarch64::getAArch64TargetCPU(Args, A);
+ return aarch64::getAArch64TargetCPU(Args, T, A);
case llvm::Triple::arm:
case llvm::Triple::armeb:
@@ -286,10 +272,6 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T,
return A->getValue();
return "";
- case llvm::Triple::nios2: {
- return getNios2TargetCPU(Args);
- }
-
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
@@ -559,6 +541,40 @@ static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args,
return false;
}
+static void addSanitizerLibPath(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs, StringRef Name) {
+ for (const auto &LibPath : TC.getLibraryPaths()) {
+ if (!LibPath.empty()) {
+ SmallString<128> P(LibPath);
+ llvm::sys::path::append(P, Name);
+ if (TC.getVFS().exists(P))
+ CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + P));
+ }
+ }
+}
+
+void tools::addSanitizerPathLibArgs(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
+ if (SanArgs.needsAsanRt()) {
+ addSanitizerLibPath(TC, Args, CmdArgs, "asan");
+ }
+ if (SanArgs.needsHwasanRt()) {
+ addSanitizerLibPath(TC, Args, CmdArgs, "hwasan");
+ }
+ if (SanArgs.needsLsanRt()) {
+ addSanitizerLibPath(TC, Args, CmdArgs, "lsan");
+ }
+ if (SanArgs.needsMsanRt()) {
+ addSanitizerLibPath(TC, Args, CmdArgs, "msan");
+ }
+ if (SanArgs.needsTsanRt()) {
+ addSanitizerLibPath(TC, Args, CmdArgs, "tsan");
+ }
+}
+
+
+
void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
ArgStringList &CmdArgs) {
// Force linking against the system libraries sanitizers depends on
@@ -568,19 +584,19 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
if (TC.getTriple().getOS() != llvm::Triple::RTEMS &&
!TC.getTriple().isAndroid()) {
CmdArgs.push_back("-lpthread");
- if (TC.getTriple().getOS() != llvm::Triple::OpenBSD)
+ if (!TC.getTriple().isOSOpenBSD())
CmdArgs.push_back("-lrt");
}
CmdArgs.push_back("-lm");
// There's no libdl on all OSes.
- if (TC.getTriple().getOS() != llvm::Triple::FreeBSD &&
- TC.getTriple().getOS() != llvm::Triple::NetBSD &&
- TC.getTriple().getOS() != llvm::Triple::OpenBSD &&
- TC.getTriple().getOS() != llvm::Triple::RTEMS)
+ if (!TC.getTriple().isOSFreeBSD() &&
+ !TC.getTriple().isOSNetBSD() &&
+ !TC.getTriple().isOSOpenBSD() &&
+ TC.getTriple().getOS() != llvm::Triple::RTEMS)
CmdArgs.push_back("-ldl");
// Required for backtrace on some OSes
- if (TC.getTriple().getOS() == llvm::Triple::NetBSD ||
- TC.getTriple().getOS() == llvm::Triple::FreeBSD)
+ if (TC.getTriple().isOSFreeBSD() ||
+ TC.getTriple().isOSNetBSD())
CmdArgs.push_back("-lexecinfo");
}
@@ -755,13 +771,13 @@ bool tools::addXRayRuntime(const ToolChain&TC, const ArgList &Args, ArgStringLis
void tools::linkXRayRuntimeDeps(const ToolChain &TC, ArgStringList &CmdArgs) {
CmdArgs.push_back("--no-as-needed");
CmdArgs.push_back("-lpthread");
- if (TC.getTriple().getOS() != llvm::Triple::OpenBSD)
+ if (!TC.getTriple().isOSOpenBSD())
CmdArgs.push_back("-lrt");
CmdArgs.push_back("-lm");
- if (TC.getTriple().getOS() != llvm::Triple::FreeBSD &&
- TC.getTriple().getOS() != llvm::Triple::NetBSD &&
- TC.getTriple().getOS() != llvm::Triple::OpenBSD)
+ if (!TC.getTriple().isOSFreeBSD() &&
+ !TC.getTriple().isOSNetBSD() &&
+ !TC.getTriple().isOSOpenBSD())
CmdArgs.push_back("-ldl");
}
@@ -773,21 +789,18 @@ bool tools::areOptimizationsEnabled(const ArgList &Args) {
return false;
}
-const char *tools::SplitDebugName(const ArgList &Args, const InputInfo &Input) {
- Arg *FinalOutput = Args.getLastArg(options::OPT_o);
- if (FinalOutput && Args.hasArg(options::OPT_c)) {
- SmallString<128> T(FinalOutput->getValue());
- llvm::sys::path::replace_extension(T, "dwo");
- return Args.MakeArgString(T);
- } else {
- // Use the compilation dir.
- SmallString<128> T(
- Args.getLastArgValue(options::OPT_fdebug_compilation_dir));
- SmallString<128> F(llvm::sys::path::stem(Input.getBaseInput()));
- llvm::sys::path::replace_extension(F, "dwo");
- T += F;
- return Args.MakeArgString(F);
- }
+const char *tools::SplitDebugName(const ArgList &Args,
+ const InputInfo &Output) {
+ SmallString<128> F(Output.isFilename()
+ ? Output.getFilename()
+ : llvm::sys::path::stem(Output.getBaseInput()));
+
+ if (Arg *A = Args.getLastArg(options::OPT_gsplit_dwarf_EQ))
+ if (StringRef(A->getValue()) == "single")
+ return Args.MakeArgString(F);
+
+ llvm::sys::path::replace_extension(F, "dwo");
+ return Args.MakeArgString(F);
}
void tools::SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T,
@@ -901,7 +914,7 @@ tools::ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) {
}
// OpenBSD-specific defaults for PIE
- if (Triple.getOS() == llvm::Triple::OpenBSD) {
+ if (Triple.isOSOpenBSD()) {
switch (ToolChain.getArch()) {
case llvm::Triple::arm:
case llvm::Triple::aarch64:
@@ -1126,23 +1139,39 @@ static void AddLibgcc(const llvm::Triple &Triple, const Driver &D,
bool IsIAMCU = Triple.isOSIAMCU();
bool StaticLibgcc = Args.hasArg(options::OPT_static_libgcc) ||
Args.hasArg(options::OPT_static);
- if (!D.CCCIsCXX())
+
+ bool SharedLibgcc = Args.hasArg(options::OPT_shared_libgcc);
+ bool UnspecifiedLibgcc = !StaticLibgcc && !SharedLibgcc;
+
+ // Gcc adds libgcc arguments in various ways:
+ //
+ // gcc <none>: -lgcc --as-needed -lgcc_s --no-as-needed
+ // g++ <none>: -lgcc_s -lgcc
+ // gcc shared: -lgcc_s -lgcc
+ // g++ shared: -lgcc_s -lgcc
+ // gcc static: -lgcc -lgcc_eh
+ // g++ static: -lgcc -lgcc_eh
+ //
+ // Also, certain targets need additional adjustments.
+
+ bool LibGccFirst = (D.CCCIsCC() && UnspecifiedLibgcc) || StaticLibgcc;
+ if (LibGccFirst)
CmdArgs.push_back("-lgcc");
- if (StaticLibgcc || isAndroid) {
- if (D.CCCIsCXX())
- CmdArgs.push_back("-lgcc");
- } else {
- if (!D.CCCIsCXX() && !isCygMing)
- CmdArgs.push_back("--as-needed");
+ bool AsNeeded = D.CCCIsCC() && UnspecifiedLibgcc && !isAndroid && !isCygMing;
+ if (AsNeeded)
+ CmdArgs.push_back("--as-needed");
+
+ if ((UnspecifiedLibgcc || SharedLibgcc) && !isAndroid)
CmdArgs.push_back("-lgcc_s");
- if (!D.CCCIsCXX() && !isCygMing)
- CmdArgs.push_back("--no-as-needed");
- }
- if (StaticLibgcc && !isAndroid && !IsIAMCU)
+ else if (StaticLibgcc && !isAndroid && !IsIAMCU)
CmdArgs.push_back("-lgcc_eh");
- else if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX())
+
+ if (AsNeeded)
+ CmdArgs.push_back("--no-as-needed");
+
+ if (!LibGccFirst)
CmdArgs.push_back("-lgcc");
// According to Android ABI, we have to link with libdl if we are
@@ -1318,6 +1347,18 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C,
if (!JA.isHostOffloading(Action::OFK_HIP))
return;
+ InputInfoList DeviceInputs;
+ for (const auto &II : Inputs) {
+ const Action *A = II.getAction();
+ // Is this a device linking action?
+ if (A && isa<LinkJobAction>(A) && A->isDeviceOffloading(Action::OFK_HIP)) {
+ DeviceInputs.push_back(II);
+ }
+ }
+
+ if (DeviceInputs.empty())
+ return;
+
// Create temporary linker script. Keep it if save-temps is enabled.
const char *LKS;
SmallString<256> Name = llvm::sys::path::filename(Output.getFilename());
@@ -1345,39 +1386,12 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C,
"Wrong platform");
(void)HIPTC;
- // Construct clang-offload-bundler command to bundle object files for
- // for different GPU archs.
- ArgStringList BundlerArgs;
- BundlerArgs.push_back(Args.MakeArgString("-type=o"));
-
- // ToDo: Remove the dummy host binary entry which is required by
- // clang-offload-bundler.
- std::string BundlerTargetArg = "-targets=host-x86_64-unknown-linux";
- std::string BundlerInputArg = "-inputs=/dev/null";
-
- for (const auto &II : Inputs) {
- const Action *A = II.getAction();
- // Is this a device linking action?
- if (A && isa<LinkJobAction>(A) && A->isDeviceOffloading(Action::OFK_HIP)) {
- BundlerTargetArg = BundlerTargetArg + ",hip-amdgcn-amd-amdhsa-" +
- StringRef(A->getOffloadingArch()).str();
- BundlerInputArg = BundlerInputArg + "," + II.getFilename();
- }
- }
- BundlerArgs.push_back(Args.MakeArgString(BundlerTargetArg));
- BundlerArgs.push_back(Args.MakeArgString(BundlerInputArg));
-
- std::string BundleFileName = C.getDriver().GetTemporaryPath("BUNDLE", "o");
+ // The output file name needs to persist through the compilation, therefore
+ // it needs to be created through MakeArgString.
+ std::string BundleFileName = C.getDriver().GetTemporaryPath("BUNDLE", "hipfb");
const char *BundleFile =
C.addTempFile(C.getArgs().MakeArgString(BundleFileName.c_str()));
- auto BundlerOutputArg =
- Args.MakeArgString(std::string("-outputs=").append(BundleFile));
- BundlerArgs.push_back(BundlerOutputArg);
-
- SmallString<128> BundlerPath(C.getDriver().Dir);
- llvm::sys::path::append(BundlerPath, "clang-offload-bundler");
- const char *Bundler = Args.MakeArgString(BundlerPath);
- C.addCommand(llvm::make_unique<Command>(JA, T, Bundler, BundlerArgs, Inputs));
+ AMDGCN::constructHIPFatbinCommand(C, JA, BundleFile, DeviceInputs, Args, T);
// Add commands to embed target binaries. We ensure that each section and
// image is 16-byte aligned. This is not mandatory, but increases the
@@ -1397,6 +1411,10 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C,
LksStream << " PROVIDE_HIDDEN(__hip_fatbin = .);\n";
LksStream << " " << BundleFileName << "\n";
LksStream << " }\n";
+ LksStream << " /DISCARD/ :\n";
+ LksStream << " {\n";
+ LksStream << " * ( __CLANG_OFFLOAD_BUNDLE__* )\n";
+ LksStream << " }\n";
LksStream << "}\n";
LksStream << "INSERT BEFORE .data\n";
LksStream.flush();
diff --git a/lib/Driver/ToolChains/CommonArgs.h b/lib/Driver/ToolChains/CommonArgs.h
index e8ebe2225e1c..3704b2e01b54 100644
--- a/lib/Driver/ToolChains/CommonArgs.h
+++ b/lib/Driver/ToolChains/CommonArgs.h
@@ -32,6 +32,10 @@ void claimNoWarnArgs(const llvm::opt::ArgList &Args);
bool addSanitizerRuntimes(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);
+void addSanitizerPathLibArgs(const ToolChain &TC,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs);
+
void linkSanitizerRuntimeDeps(const ToolChain &TC,
llvm::opt::ArgStringList &CmdArgs);
@@ -59,7 +63,7 @@ void AddHIPLinkerScript(const ToolChain &TC, Compilation &C,
const Tool &T);
const char *SplitDebugName(const llvm::opt::ArgList &Args,
- const InputInfo &Input);
+ const InputInfo &Output);
void SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T,
const JobAction &JA, const llvm::opt::ArgList &Args,
diff --git a/lib/Driver/ToolChains/CrossWindows.cpp b/lib/Driver/ToolChains/CrossWindows.cpp
index 6ca04a8a3abb..795356026fbe 100644
--- a/lib/Driver/ToolChains/CrossWindows.cpp
+++ b/lib/Driver/ToolChains/CrossWindows.cpp
@@ -20,6 +20,7 @@ using namespace clang::driver;
using namespace clang::driver::toolchains;
using llvm::opt::ArgList;
+using llvm::opt::ArgStringList;
void tools::CrossWindows::Assembler::ConstructJob(
Compilation &C, const JobAction &JA, const InputInfo &Output,
diff --git a/lib/Driver/ToolChains/Cuda.cpp b/lib/Driver/ToolChains/Cuda.cpp
index 7fb4ae4ea9cf..57b8d4340e3b 100644
--- a/lib/Driver/ToolChains/Cuda.cpp
+++ b/lib/Driver/ToolChains/Cuda.cpp
@@ -11,7 +11,6 @@
#include "CommonArgs.h"
#include "InputInfo.h"
#include "clang/Basic/Cuda.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Distro.h"
@@ -23,6 +22,7 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <system_error>
using namespace clang::driver;
@@ -59,6 +59,8 @@ static CudaVersion ParseCudaVersionFile(llvm::StringRef V) {
return CudaVersion::CUDA_91;
if (Major == 9 && Minor == 2)
return CudaVersion::CUDA_92;
+ if (Major == 10 && Minor == 0)
+ return CudaVersion::CUDA_100;
return CudaVersion::UNKNOWN;
}
@@ -112,7 +114,7 @@ CudaInstallationDetector::CudaInstallationDetector(
for (const char *Ver : Versions)
Candidates.emplace_back(D.SysRoot + "/usr/local/cuda-" + Ver);
- if (Distro(D.getVFS()).IsDebian())
+ if (Distro(D.getVFS()).IsDebian() || Distro(D.getVFS()).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");
@@ -165,7 +167,7 @@ CudaInstallationDetector::CudaInstallationDetector(
if (FS.exists(FilePath)) {
for (const char *GpuArchName :
{"sm_30", "sm_32", "sm_35", "sm_37", "sm_50", "sm_52", "sm_53",
- "sm_60", "sm_61", "sm_62", "sm_70", "sm_72"}) {
+ "sm_60", "sm_61", "sm_62", "sm_70", "sm_72", "sm_75"}) {
const CudaArch GpuArch = StringToCudaArch(GpuArchName);
if (Version >= MinVersionForCudaArch(GpuArch) &&
Version <= MaxVersionForCudaArch(GpuArch))
@@ -276,32 +278,44 @@ void CudaInstallationDetector::print(raw_ostream &OS) const {
}
namespace {
- /// Debug info kind.
-enum DebugInfoKind {
- NoDebug, /// No debug info.
- LineTableOnly, /// Line tables only.
- FullDebug /// Full debug info.
+/// Debug info level for the NVPTX devices. We may need to emit different debug
+/// info level for the host and for the device itselfi. This type controls
+/// emission of the debug info for the devices. It either prohibits disable info
+/// emission completely, or emits debug directives only, or emits same debug
+/// info as for the host.
+enum DeviceDebugInfoLevel {
+ DisableDebugInfo, /// Do not emit debug info for the devices.
+ DebugDirectivesOnly, /// Emit only debug directives.
+ EmitSameDebugInfoAsHost, /// Use the same debug info level just like for the
+ /// host.
};
} // anonymous namespace
-static DebugInfoKind mustEmitDebugInfo(const ArgList &Args) {
- Arg *A = Args.getLastArg(options::OPT_O_Group);
- if (Args.hasFlag(options::OPT_cuda_noopt_device_debug,
- options::OPT_no_cuda_noopt_device_debug,
- !A || A->getOption().matches(options::OPT_O0))) {
- if (const Arg *A = Args.getLastArg(options::OPT_g_Group)) {
- const Option &Opt = A->getOption();
- if (Opt.matches(options::OPT_gN_Group)) {
- if (Opt.matches(options::OPT_g0) || Opt.matches(options::OPT_ggdb0))
- return NoDebug;
- if (Opt.matches(options::OPT_gline_tables_only) ||
- Opt.matches(options::OPT_ggdb1))
- return LineTableOnly;
- }
- return FullDebug;
+/// Define debug info level for the NVPTX devices. If the debug info for both
+/// the host and device are disabled (-g0/-ggdb0 or no debug options at all). If
+/// only debug directives are requested for the both host and device
+/// (-gline-directvies-only), or the debug info only for the device is disabled
+/// (optimization is on and --cuda-noopt-device-debug was not specified), the
+/// debug directves only must be emitted for the device. Otherwise, use the same
+/// debug info level just like for the host (with the limitations of only
+/// supported DWARF2 standard).
+static DeviceDebugInfoLevel mustEmitDebugInfo(const ArgList &Args) {
+ const Arg *A = Args.getLastArg(options::OPT_O_Group);
+ bool IsDebugEnabled = !A || A->getOption().matches(options::OPT_O0) ||
+ Args.hasFlag(options::OPT_cuda_noopt_device_debug,
+ options::OPT_no_cuda_noopt_device_debug,
+ /*Default=*/false);
+ if (const Arg *A = Args.getLastArg(options::OPT_g_Group)) {
+ const Option &Opt = A->getOption();
+ if (Opt.matches(options::OPT_gN_Group)) {
+ if (Opt.matches(options::OPT_g0) || Opt.matches(options::OPT_ggdb0))
+ return DisableDebugInfo;
+ if (Opt.matches(options::OPT_gline_directives_only))
+ return DebugDirectivesOnly;
}
+ return IsDebugEnabled ? EmitSameDebugInfoAsHost : DebugDirectivesOnly;
}
- return NoDebug;
+ return DisableDebugInfo;
}
void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
@@ -335,8 +349,8 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
ArgStringList CmdArgs;
CmdArgs.push_back(TC.getTriple().isArch64Bit() ? "-m64" : "-m32");
- DebugInfoKind DIKind = mustEmitDebugInfo(Args);
- if (DIKind == FullDebug) {
+ DeviceDebugInfoLevel DIKind = mustEmitDebugInfo(Args);
+ if (DIKind == EmitSameDebugInfoAsHost) {
// ptxas does not accept -g option if optimization is enabled, so
// we ignore the compiler's -O* options if we want debug info.
CmdArgs.push_back("-g");
@@ -372,7 +386,7 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
// to no optimizations, but ptxas's default is -O3.
CmdArgs.push_back("-O0");
}
- if (DIKind == LineTableOnly)
+ if (DIKind == DebugDirectivesOnly)
CmdArgs.push_back("-lineinfo");
// Pass -v to ptxas if it was passed to the driver.
@@ -396,8 +410,8 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fnoopenmp_relocatable_target,
/*Default=*/true);
else if (JA.isOffloading(Action::OFK_Cuda))
- Relocatable = Args.hasFlag(options::OPT_fcuda_rdc,
- options::OPT_fno_cuda_rdc, /*Default=*/false);
+ Relocatable = Args.hasFlag(options::OPT_fgpu_rdc,
+ options::OPT_fno_gpu_rdc, /*Default=*/false);
if (Relocatable)
CmdArgs.push_back("-c");
@@ -443,7 +457,7 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(TC.getTriple().isArch64Bit() ? "-64" : "-32");
CmdArgs.push_back(Args.MakeArgString("--create"));
CmdArgs.push_back(Args.MakeArgString(Output.getFilename()));
- if (mustEmitDebugInfo(Args) == FullDebug)
+ if (mustEmitDebugInfo(Args) == EmitSameDebugInfoAsHost)
CmdArgs.push_back("-g");
for (const auto& II : Inputs) {
@@ -496,7 +510,7 @@ void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Output.getFilename());
} else
assert(Output.isNothing() && "Invalid output.");
- if (mustEmitDebugInfo(Args) == FullDebug)
+ if (mustEmitDebugInfo(Args) == EmitSameDebugInfoAsHost)
CmdArgs.push_back("-g");
if (Args.hasArg(options::OPT_v))
@@ -509,6 +523,11 @@ void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-arch");
CmdArgs.push_back(Args.MakeArgString(GPUArch));
+ // Assume that the directory specified with --libomptarget_nvptx_path
+ // contains the static library libomptarget-nvptx.a.
+ if (const Arg *A = Args.getLastArg(options::OPT_libomptarget_nvptx_path_EQ))
+ CmdArgs.push_back(Args.MakeArgString(Twine("-L") + A->getValue()));
+
// Add paths specified in LIBRARY_PATH environment variable as -L options.
addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH");
@@ -602,9 +621,9 @@ void CudaToolChain::addClangTargetOptions(
options::OPT_fno_cuda_approx_transcendentals, false))
CC1Args.push_back("-fcuda-approx-transcendentals");
- if (DriverArgs.hasFlag(options::OPT_fcuda_rdc, options::OPT_fno_cuda_rdc,
+ if (DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
false))
- CC1Args.push_back("-fcuda-rdc");
+ CC1Args.push_back("-fgpu-rdc");
}
if (DriverArgs.hasArg(options::OPT_nocudalib))
@@ -621,13 +640,16 @@ void CudaToolChain::addClangTargetOptions(
return;
}
- CC1Args.push_back("-mlink-cuda-bitcode");
+ CC1Args.push_back("-mlink-builtin-bitcode");
CC1Args.push_back(DriverArgs.MakeArgString(LibDeviceFile));
// Libdevice in CUDA-7.0 requires PTX version that's more recent than LLVM
// defaults to. Use PTX4.2 by default, which is the PTX version that came with
// CUDA-7.0.
const char *PtxFeature = "+ptx42";
+ // TODO(tra): CUDA-10+ needs PTX 6.3 to support new features. However that
+ // requires fair amount of work on LLVM side. We'll keep using PTX 6.1 until
+ // all prerequisites are in place.
if (CudaInstallation.version() >= CudaVersion::CUDA_91) {
// CUDA-9.1 uses new instructions that are only available in PTX6.1+
PtxFeature = "+ptx61";
@@ -642,12 +664,9 @@ void CudaToolChain::addClangTargetOptions(
if (DeviceOffloadingKind == Action::OFK_OpenMP) {
SmallVector<StringRef, 8> LibraryPaths;
- // Add path to lib and/or lib64 folders.
- SmallString<256> DefaultLibPath =
- llvm::sys::path::parent_path(getDriver().Dir);
- llvm::sys::path::append(DefaultLibPath,
- Twine("lib") + CLANG_LIBDIR_SUFFIX);
- LibraryPaths.emplace_back(DefaultLibPath.c_str());
+
+ if (const Arg *A = DriverArgs.getLastArg(options::OPT_libomptarget_nvptx_path_EQ))
+ LibraryPaths.push_back(A->getValue());
// Add user defined library paths from LIBRARY_PATH.
llvm::Optional<std::string> LibPath =
@@ -660,6 +679,12 @@ void CudaToolChain::addClangTargetOptions(
LibraryPaths.emplace_back(Path.trim());
}
+ // Add path to lib / lib64 folder.
+ SmallString<256> DefaultLibPath =
+ llvm::sys::path::parent_path(getDriver().Dir);
+ llvm::sys::path::append(DefaultLibPath, Twine("lib") + CLANG_LIBDIR_SUFFIX);
+ LibraryPaths.emplace_back(DefaultLibPath.c_str());
+
std::string LibOmpTargetName =
"libomptarget-nvptx-" + GpuArch.str() + ".bc";
bool FoundBCLibrary = false;
@@ -667,7 +692,7 @@ void CudaToolChain::addClangTargetOptions(
SmallString<128> LibOmpTargetFile(LibraryPath);
llvm::sys::path::append(LibOmpTargetFile, LibOmpTargetName);
if (llvm::sys::fs::exists(LibOmpTargetFile)) {
- CC1Args.push_back("-mlink-cuda-bitcode");
+ CC1Args.push_back("-mlink-builtin-bitcode");
CC1Args.push_back(DriverArgs.MakeArgString(LibOmpTargetFile));
FoundBCLibrary = true;
break;
@@ -691,6 +716,21 @@ bool CudaToolChain::supportsDebugInfoOption(const llvm::opt::Arg *A) const {
O.matches(options::OPT_gcolumn_info);
}
+void CudaToolChain::adjustDebugInfoKind(
+ codegenoptions::DebugInfoKind &DebugInfoKind, const ArgList &Args) const {
+ switch (mustEmitDebugInfo(Args)) {
+ case DisableDebugInfo:
+ DebugInfoKind = codegenoptions::NoDebugInfo;
+ break;
+ case DebugDirectivesOnly:
+ DebugInfoKind = codegenoptions::DebugDirectivesOnly;
+ break;
+ case EmitSameDebugInfoAsHost:
+ // Use same debug info level as the host.
+ break;
+ }
+}
+
void CudaToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
// Check our CUDA version if we're going to include the CUDA headers.
diff --git a/lib/Driver/ToolChains/Cuda.h b/lib/Driver/ToolChains/Cuda.h
index 01580cb66920..1d63ede41155 100644
--- a/lib/Driver/ToolChains/Cuda.h
+++ b/lib/Driver/ToolChains/Cuda.h
@@ -159,6 +159,8 @@ public:
bool isPICDefaultForced() const override { return false; }
bool SupportsProfiling() const override { return false; }
bool supportsDebugInfoOption(const llvm::opt::Arg *A) const override;
+ void adjustDebugInfoKind(codegenoptions::DebugInfoKind &DebugInfoKind,
+ const llvm::opt::ArgList &Args) const override;
bool IsMathErrnoDefault() const override { return false; }
void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
diff --git a/lib/Driver/ToolChains/Darwin.cpp b/lib/Driver/ToolChains/Darwin.cpp
index 9205dd52de0b..c395c9a4430e 100644
--- a/lib/Driver/ToolChains/Darwin.cpp
+++ b/lib/Driver/ToolChains/Darwin.cpp
@@ -12,7 +12,6 @@
#include "CommonArgs.h"
#include "clang/Basic/AlignedAllocation.h"
#include "clang/Basic/ObjCRuntime.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
@@ -23,6 +22,7 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/TargetParser.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <cstdlib> // ::getenv
using namespace clang::driver;
@@ -98,7 +98,7 @@ void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
SourceAction = SourceAction->getInputs()[0];
}
- // If -fno-integrated-as is used add -Q to the darwin assember driver to make
+ // If -fno-integrated-as is used add -Q to the darwin assembler driver to make
// sure it runs its system assembler not clang's integrated assembler.
// Applicable to darwin11+ and Xcode 4+. darwin<10 lacked integrated-as.
// FIXME: at run-time detect assembler capabilities or rely on version
@@ -224,13 +224,20 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
options::OPT_fno_application_extension, false))
CmdArgs.push_back("-application_extension");
- if (D.isUsingLTO()) {
- // If we are using LTO, then automatically create a temporary file path for
- // the linker to use, so that it's lifetime will extend past a possible
- // dsymutil step.
- if (Version[0] >= 116 && NeedsTempPath(Inputs)) {
- const char *TmpPath = C.getArgs().MakeArgString(
- D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object)));
+ if (D.isUsingLTO() && Version[0] >= 116 && NeedsTempPath(Inputs)) {
+ std::string TmpPathName;
+ if (D.getLTOMode() == LTOK_Full) {
+ // If we are using full LTO, then automatically create a temporary file
+ // path for the linker to use, so that it's lifetime will extend past a
+ // possible dsymutil step.
+ TmpPathName =
+ D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object));
+ } else if (D.getLTOMode() == LTOK_Thin)
+ // If we are using thin LTO, then create a directory instead.
+ TmpPathName = D.GetTemporaryDirectory("thinlto");
+
+ if (!TmpPathName.empty()) {
+ auto *TmpPath = C.getArgs().MakeArgString(TmpPathName);
C.addTempFile(TmpPath);
CmdArgs.push_back("-object_path_lto");
CmdArgs.push_back(TmpPath);
@@ -509,15 +516,6 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);
- // SafeStack requires its own runtime libraries
- // These libraries should be linked first, to make sure the
- // __safestack_init constructor executes before everything else
- if (getToolChain().getSanitizerArgs().needsSafeStackRt()) {
- getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs,
- "libclang_rt.safestack_osx.a",
- toolchains::Darwin::RLO_AlwaysLink);
- }
-
Args.AddAllArgs(CmdArgs, options::OPT_L);
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
@@ -917,8 +915,19 @@ unsigned DarwinClang::GetDefaultDwarfVersion() const {
}
void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
- StringRef DarwinLibName,
- RuntimeLinkOptions Opts) const {
+ StringRef Component, RuntimeLinkOptions Opts,
+ bool IsShared) const {
+ SmallString<64> DarwinLibName = StringRef("libclang_rt.");
+ // an Darwin the builtins compomnent is not in the library name
+ if (Component != "builtins") {
+ DarwinLibName += Component;
+ if (!(Opts & RLO_IsEmbedded))
+ DarwinLibName += "_";
+ DarwinLibName += getOSLibraryNameSuffix();
+ } else
+ DarwinLibName += getOSLibraryNameSuffix(true);
+
+ DarwinLibName += IsShared ? "_dynamic.dylib" : ".a";
SmallString<128> Dir(getDriver().ResourceDir);
llvm::sys::path::append(
Dir, "lib", (Opts & RLO_IsEmbedded) ? "macho_embedded" : "darwin");
@@ -983,16 +992,19 @@ StringRef Darwin::getSDKName(StringRef isysroot) {
return "";
}
-StringRef Darwin::getOSLibraryNameSuffix() const {
- switch(TargetPlatform) {
+StringRef Darwin::getOSLibraryNameSuffix(bool IgnoreSim) const {
+ switch (TargetPlatform) {
case DarwinPlatformKind::MacOS:
return "osx";
case DarwinPlatformKind::IPhoneOS:
- return TargetEnvironment == NativeEnvironment ? "ios" : "iossim";
+ return TargetEnvironment == NativeEnvironment || IgnoreSim ? "ios"
+ : "iossim";
case DarwinPlatformKind::TvOS:
- return TargetEnvironment == NativeEnvironment ? "tvos" : "tvossim";
+ return TargetEnvironment == NativeEnvironment || IgnoreSim ? "tvos"
+ : "tvossim";
case DarwinPlatformKind::WatchOS:
- return TargetEnvironment == NativeEnvironment ? "watchos" : "watchossim";
+ return TargetEnvironment == NativeEnvironment || IgnoreSim ? "watchos"
+ : "watchossim";
}
llvm_unreachable("Unsupported platform");
}
@@ -1022,18 +1034,24 @@ void Darwin::addProfileRTLibs(const ArgList &Args,
ArgStringList &CmdArgs) const {
if (!needsProfileRT(Args)) return;
- AddLinkRuntimeLib(
- Args, CmdArgs,
- (Twine("libclang_rt.profile_") + getOSLibraryNameSuffix() + ".a").str(),
- RuntimeLinkOptions(RLO_AlwaysLink | RLO_FirstLink));
+ AddLinkRuntimeLib(Args, CmdArgs, "profile",
+ RuntimeLinkOptions(RLO_AlwaysLink | RLO_FirstLink));
// 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)) {
- addExportedSymbol(CmdArgs, "___llvm_profile_filename");
- addExportedSymbol(CmdArgs, "___llvm_profile_raw_version");
- addExportedSymbol(CmdArgs, "_lprofCurFilename");
+ if (needsGCovInstrumentation(Args)) {
+ addExportedSymbol(CmdArgs, "___gcov_flush");
+ addExportedSymbol(CmdArgs, "_flush_fn_list");
+ addExportedSymbol(CmdArgs, "_writeout_fn_list");
+ } else {
+ addExportedSymbol(CmdArgs, "___llvm_profile_filename");
+ addExportedSymbol(CmdArgs, "___llvm_profile_raw_version");
+ addExportedSymbol(CmdArgs, "_lprofCurFilename");
+ addExportedSymbol(CmdArgs, "_lprofMergeValueProfData");
+ }
+ addExportedSymbol(CmdArgs, "_lprofDirMode");
}
}
@@ -1042,12 +1060,7 @@ void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args,
StringRef Sanitizer,
bool Shared) const {
auto RLO = RuntimeLinkOptions(RLO_AlwaysLink | (Shared ? RLO_AddRPath : 0U));
- AddLinkRuntimeLib(Args, CmdArgs,
- (Twine("libclang_rt.") + Sanitizer + "_" +
- getOSLibraryNameSuffix() +
- (Shared ? "_dynamic.dylib" : ".a"))
- .str(),
- RLO);
+ AddLinkRuntimeLib(Args, CmdArgs, Sanitizer, RLO, Shared);
}
ToolChain::RuntimeLibType DarwinClang::GetRuntimeLibType(
@@ -1101,66 +1114,33 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
AddCXXStdlibLibArgs(Args, CmdArgs);
}
if (Sanitize.needsStatsRt()) {
- StringRef OS = isTargetMacOS() ? "osx" : "iossim";
- AddLinkRuntimeLib(Args, CmdArgs,
- (Twine("libclang_rt.stats_client_") + OS + ".a").str(),
- RLO_AlwaysLink);
+ AddLinkRuntimeLib(Args, CmdArgs, "stats_client", RLO_AlwaysLink);
AddLinkSanitizerLibArgs(Args, CmdArgs, "stats");
}
if (Sanitize.needsEsanRt())
AddLinkSanitizerLibArgs(Args, CmdArgs, "esan");
+ const XRayArgs &XRay = getXRayArgs();
+ if (XRay.needsXRayRt()) {
+ AddLinkRuntimeLib(Args, CmdArgs, "xray");
+ AddLinkRuntimeLib(Args, CmdArgs, "xray-basic");
+ AddLinkRuntimeLib(Args, CmdArgs, "xray-fdr");
+ }
+
// Otherwise link libSystem, then the dynamic runtime library, and finally any
// target specific static runtime library.
CmdArgs.push_back("-lSystem");
// Select the dynamic runtime library and the target specific static library.
- if (isTargetWatchOSBased()) {
- // We currently always need a static runtime library for watchOS.
- AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.watchos.a");
- } else if (isTargetTvOSBased()) {
- // We currently always need a static runtime library for tvOS.
- AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.tvos.a");
- } else if (isTargetIOSBased()) {
+ if (isTargetIOSBased()) {
// If we are compiling as iOS / simulator, don't attempt to link libgcc_s.1,
// it never went into the SDK.
// Linking against libgcc_s.1 isn't needed for iOS 5.0+
if (isIPhoneOSVersionLT(5, 0) && !isTargetIOSSimulator() &&
getTriple().getArch() != llvm::Triple::aarch64)
CmdArgs.push_back("-lgcc_s.1");
-
- // We currently always need a static runtime library for iOS.
- AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.ios.a");
- } else {
- assert(isTargetMacOS() && "unexpected non MacOS platform");
- // The dynamic runtime library was merged with libSystem for 10.6 and
- // beyond; only 10.4 and 10.5 need an additional runtime library.
- if (isMacosxVersionLT(10, 5))
- CmdArgs.push_back("-lgcc_s.10.4");
- else if (isMacosxVersionLT(10, 6))
- CmdArgs.push_back("-lgcc_s.10.5");
-
- // Originally for OS X, we thought we would only need a static runtime
- // library when targeting 10.4, to provide versions of the static functions
- // which were omitted from 10.4.dylib. This led to the creation of the 10.4
- // builtins library.
- //
- // Unfortunately, that turned out to not be true, because Darwin system
- // headers can still use eprintf on i386, and it is not exported from
- // libSystem. Therefore, we still must provide a runtime library just for
- // the tiny tiny handful of projects that *might* use that symbol.
- //
- // Then over time, we figured out it was useful to add more things to the
- // runtime so we created libclang_rt.osx.a to provide new functions when
- // deploying to old OS builds, and for a long time we had both eprintf and
- // osx builtin libraries. Which just seems excessive. So with PR 28855, we
- // are removing the eprintf library and expecting eprintf to be provided by
- // the OS X builtins library.
- if (isMacosxVersionLT(10, 5))
- AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.10.4.a");
- else
- AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.osx.a");
}
+ AddLinkRuntimeLib(Args, CmdArgs, "builtins");
}
/// Returns the most appropriate macOS target version for the current process.
@@ -1314,6 +1294,18 @@ struct DarwinPlatform {
return DarwinPlatform(InferredFromArch, getPlatformFromOS(OS), Value);
}
+ /// Constructs an inferred SDKInfo value based on the version inferred from
+ /// the SDK path itself. Only works for values that were created by inferring
+ /// the platform from the SDKPath.
+ DarwinSDKInfo inferSDKInfo() {
+ assert(Kind == InferredFromSDK && "can infer SDK info only");
+ llvm::VersionTuple Version;
+ bool IsValid = !Version.tryParse(OSVersion);
+ (void)IsValid;
+ assert(IsValid && "invalid SDK version");
+ return DarwinSDKInfo(Version);
+ }
+
private:
DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, Arg *Argument)
: Kind(Kind), Platform(Platform), Argument(Argument) {}
@@ -1447,8 +1439,11 @@ getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver,
}
/// Tries to infer the deployment target from the SDK specified by -isysroot
-/// (or SDKROOT).
-Optional<DarwinPlatform> inferDeploymentTargetFromSDK(DerivedArgList &Args) {
+/// (or SDKROOT). Uses the version specified in the SDKSettings.json file if
+/// it's available.
+Optional<DarwinPlatform>
+inferDeploymentTargetFromSDK(DerivedArgList &Args,
+ const Optional<DarwinSDKInfo> &SDKInfo) {
const Arg *A = Args.getLastArg(options::OPT_isysroot);
if (!A)
return None;
@@ -1456,28 +1451,37 @@ Optional<DarwinPlatform> inferDeploymentTargetFromSDK(DerivedArgList &Args) {
StringRef SDK = Darwin::getSDKName(isysroot);
if (!SDK.size())
return None;
- // Slice the version number out.
- // Version number is between the first and the last number.
- size_t StartVer = SDK.find_first_of("0123456789");
- size_t EndVer = SDK.find_last_of("0123456789");
- if (StartVer != StringRef::npos && EndVer > StartVer) {
- StringRef Version = SDK.slice(StartVer, EndVer + 1);
- if (SDK.startswith("iPhoneOS") || SDK.startswith("iPhoneSimulator"))
- return DarwinPlatform::createFromSDK(
- Darwin::IPhoneOS, Version,
- /*IsSimulator=*/SDK.startswith("iPhoneSimulator"));
- else if (SDK.startswith("MacOSX"))
- return DarwinPlatform::createFromSDK(Darwin::MacOS,
- getSystemOrSDKMacOSVersion(Version));
- else if (SDK.startswith("WatchOS") || SDK.startswith("WatchSimulator"))
- return DarwinPlatform::createFromSDK(
- Darwin::WatchOS, Version,
- /*IsSimulator=*/SDK.startswith("WatchSimulator"));
- else if (SDK.startswith("AppleTVOS") || SDK.startswith("AppleTVSimulator"))
- return DarwinPlatform::createFromSDK(
- Darwin::TvOS, Version,
- /*IsSimulator=*/SDK.startswith("AppleTVSimulator"));
- }
+
+ std::string Version;
+ if (SDKInfo) {
+ // Get the version from the SDKSettings.json if it's available.
+ Version = SDKInfo->getVersion().getAsString();
+ } else {
+ // Slice the version number out.
+ // Version number is between the first and the last number.
+ size_t StartVer = SDK.find_first_of("0123456789");
+ size_t EndVer = SDK.find_last_of("0123456789");
+ if (StartVer != StringRef::npos && EndVer > StartVer)
+ Version = SDK.slice(StartVer, EndVer + 1);
+ }
+ if (Version.empty())
+ return None;
+
+ if (SDK.startswith("iPhoneOS") || SDK.startswith("iPhoneSimulator"))
+ return DarwinPlatform::createFromSDK(
+ Darwin::IPhoneOS, Version,
+ /*IsSimulator=*/SDK.startswith("iPhoneSimulator"));
+ else if (SDK.startswith("MacOSX"))
+ return DarwinPlatform::createFromSDK(Darwin::MacOS,
+ getSystemOrSDKMacOSVersion(Version));
+ else if (SDK.startswith("WatchOS") || SDK.startswith("WatchSimulator"))
+ return DarwinPlatform::createFromSDK(
+ Darwin::WatchOS, Version,
+ /*IsSimulator=*/SDK.startswith("WatchSimulator"));
+ else if (SDK.startswith("AppleTVOS") || SDK.startswith("AppleTVSimulator"))
+ return DarwinPlatform::createFromSDK(
+ Darwin::TvOS, Version,
+ /*IsSimulator=*/SDK.startswith("AppleTVSimulator"));
return None;
}
@@ -1552,6 +1556,22 @@ Optional<DarwinPlatform> getDeploymentTargetFromTargetArg(
Args.getLastArg(options::OPT_target));
}
+Optional<DarwinSDKInfo> parseSDKSettings(llvm::vfs::FileSystem &VFS,
+ const ArgList &Args,
+ const Driver &TheDriver) {
+ const Arg *A = Args.getLastArg(options::OPT_isysroot);
+ if (!A)
+ return None;
+ StringRef isysroot = A->getValue();
+ auto SDKInfoOrErr = driver::parseDarwinSDKInfo(VFS, isysroot);
+ if (!SDKInfoOrErr) {
+ llvm::consumeError(SDKInfoOrErr.takeError());
+ TheDriver.Diag(diag::warn_drv_darwin_sdk_invalid_settings);
+ return None;
+ }
+ return *SDKInfoOrErr;
+}
+
} // namespace
void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
@@ -1576,6 +1596,10 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
}
}
+ // Read the SDKSettings.json file for more information, like the SDK version
+ // that we can pass down to the compiler.
+ SDKInfo = parseSDKSettings(getVFS(), Args, getDriver());
+
// The OS and the version can be specified using the -target argument.
Optional<DarwinPlatform> OSTarget =
getDeploymentTargetFromTargetArg(Args, getTriple(), getDriver());
@@ -1621,16 +1645,22 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
getDeploymentTargetFromEnvironmentVariables(getDriver(), getTriple());
if (OSTarget) {
// Don't infer simulator from the arch when the SDK is also specified.
- Optional<DarwinPlatform> SDKTarget = inferDeploymentTargetFromSDK(Args);
+ Optional<DarwinPlatform> SDKTarget =
+ inferDeploymentTargetFromSDK(Args, SDKInfo);
if (SDKTarget)
OSTarget->setEnvironment(SDKTarget->getEnvironment());
}
}
// If there is no command-line argument to specify the Target version and
// no environment variable defined, see if we can set the default based
- // on -isysroot.
- if (!OSTarget)
- OSTarget = inferDeploymentTargetFromSDK(Args);
+ // on -isysroot using SDKSettings.json if it exists.
+ if (!OSTarget) {
+ OSTarget = inferDeploymentTargetFromSDK(Args, SDKInfo);
+ /// If the target was successfully constructed from the SDK path, try to
+ /// infer the SDK info if the SDK doesn't have it.
+ if (OSTarget && !SDKInfo)
+ SDKInfo = OSTarget->inferSDKInfo();
+ }
// If no OS targets have been specified, try to guess platform from -target
// or arch name and compute the version from the triple.
if (!OSTarget)
@@ -1709,6 +1739,39 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
}
}
+void DarwinClang::AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ // The implementation from a base class will pass through the -stdlib to
+ // CC1Args.
+ // FIXME: this should not be necessary, remove usages in the frontend
+ // (e.g. HeaderSearchOptions::UseLibcxx) and don't pipe -stdlib.
+ ToolChain::AddClangCXXStdlibIncludeArgs(DriverArgs, CC1Args);
+
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
+ DriverArgs.hasArg(options::OPT_nostdincxx))
+ return;
+
+ switch (GetCXXStdlibType(DriverArgs)) {
+ case ToolChain::CST_Libcxx: {
+ llvm::StringRef InstallDir = getDriver().getInstalledDir();
+ if (InstallDir.empty())
+ break;
+ // On Darwin, libc++ may be installed alongside the compiler in
+ // include/c++/v1.
+ // Get from 'foo/bin' to 'foo/include/c++/v1'.
+ SmallString<128> P = InstallDir;
+ // Note that InstallDir can be relative, so we have to '..' and not
+ // parent_path.
+ llvm::sys::path::append(P, "..", "include", "c++", "v1");
+ addSystemInclude(DriverArgs, CC1Args, P);
+ break;
+ }
+ case ToolChain::CST_Libstdcxx:
+ // FIXME: should we do something about it?
+ break;
+ }
+}
void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
CXXStdlibType Type = GetCXXStdlibType(Args);
@@ -1962,12 +2025,8 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
else if (Name == "pentIIm3")
DAL->AddJoinedArg(nullptr, MArch, "pentium2");
- else if (Name == "x86_64")
- DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));
- else if (Name == "x86_64h") {
+ else if (Name == "x86_64" || Name == "x86_64h")
DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));
- DAL->AddJoinedArg(nullptr, MArch, "x86_64h");
- }
else if (Name == "arm")
DAL->AddJoinedArg(nullptr, MArch, "armv4t");
@@ -2001,12 +2060,12 @@ void MachO::AddLinkRuntimeLibArgs(const ArgList &Args,
// Embedded targets are simple at the moment, not supporting sanitizers and
// with different libraries for each member of the product { static, PIC } x
// { hard-float, soft-float }
- llvm::SmallString<32> CompilerRT = StringRef("libclang_rt.");
+ llvm::SmallString<32> CompilerRT = StringRef("");
CompilerRT +=
(tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard)
? "hard"
: "soft";
- CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic.a" : "_static.a";
+ CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic" : "_static";
AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, RLO_IsEmbedded);
}
@@ -2035,8 +2094,21 @@ bool Darwin::isAlignedAllocationUnavailable() const {
void Darwin::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadKind) const {
- if (isAlignedAllocationUnavailable())
+ // Pass "-faligned-alloc-unavailable" only when the user hasn't manually
+ // enabled or disabled aligned allocations.
+ if (!DriverArgs.hasArgNoClaim(options::OPT_faligned_allocation,
+ options::OPT_fno_aligned_allocation) &&
+ isAlignedAllocationUnavailable())
CC1Args.push_back("-faligned-alloc-unavailable");
+
+ if (SDKInfo) {
+ /// Pass the SDK version to the compiler when the SDK information is
+ /// available.
+ std::string Arg;
+ llvm::raw_string_ostream OS(Arg);
+ OS << "-target-sdk-version=" << SDKInfo->getVersion();
+ CC1Args.push_back(DriverArgs.MakeArgString(OS.str()));
+ }
}
DerivedArgList *
@@ -2131,7 +2203,7 @@ llvm::ExceptionHandling Darwin::GetExceptionModel(const ArgList &Args) const {
// Only watchOS uses the new DWARF/Compact unwinding method.
llvm::Triple Triple(ComputeLLVMTriple(Args));
- if(Triple.isWatchABI())
+ if (Triple.isWatchABI())
return llvm::ExceptionHandling::DwarfCFI;
return llvm::ExceptionHandling::SjLj;
@@ -2268,8 +2340,7 @@ void Darwin::addStartObjectFileArgs(const ArgList &Args,
}
if (!isTargetIPhoneOS() && Args.hasArg(options::OPT_shared_libgcc) &&
- !isTargetWatchOS() &&
- isMacosxVersionLT(10, 5)) {
+ !isTargetWatchOS() && isMacosxVersionLT(10, 5)) {
const char *Str = Args.MakeArgString(GetFilePath("crt3.o"));
CmdArgs.push_back(Str);
}
@@ -2290,10 +2361,15 @@ SanitizerMask Darwin::getSupportedSanitizers() const {
Res |= SanitizerKind::Fuzzer;
Res |= SanitizerKind::FuzzerNoLink;
Res |= SanitizerKind::Function;
+
+ // Prior to 10.9, macOS shipped a version of the C++ standard library without
+ // C++11 support. The same is true of iOS prior to version 5. These OS'es are
+ // incompatible with -fsanitize=vptr.
+ if (!(isTargetMacOS() && isMacosxVersionLT(10, 9))
+ && !(isTargetIPhoneOS() && isIPhoneOSVersionLT(5, 0)))
+ Res |= SanitizerKind::Vptr;
+
if (isTargetMacOS()) {
- if (!isMacosxVersionLT(10, 9))
- Res |= SanitizerKind::Vptr;
- Res |= SanitizerKind::SafeStack;
if (IsX86_64)
Res |= SanitizerKind::Thread;
} else if (isTargetIOSSimulator() || isTargetTvOSSimulator()) {
diff --git a/lib/Driver/ToolChains/Darwin.h b/lib/Driver/ToolChains/Darwin.h
index 87d553bd7e0b..d753f8967a61 100644
--- a/lib/Driver/ToolChains/Darwin.h
+++ b/lib/Driver/ToolChains/Darwin.h
@@ -11,8 +11,10 @@
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H
#include "Cuda.h"
+#include "clang/Driver/DarwinSDKInfo.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
+#include "clang/Driver/XRayArgs.h"
namespace clang {
namespace driver {
@@ -189,9 +191,9 @@ public:
/// Add a runtime library to the list of items to link.
void AddLinkRuntimeLib(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs,
- StringRef DarwinLibName,
- RuntimeLinkOptions Opts = RuntimeLinkOptions()) const;
+ llvm::opt::ArgStringList &CmdArgs, StringRef Component,
+ RuntimeLinkOptions Opts = RuntimeLinkOptions(),
+ bool IsShared = false) const;
/// Add any profiling runtime libraries that are needed. This is essentially a
/// MachO specific version of addProfileRT in Tools.cpp.
@@ -252,6 +254,10 @@ public:
return llvm::ExceptionHandling::None;
}
+ virtual StringRef getOSLibraryNameSuffix(bool IgnoreSim = false) const {
+ return "";
+ }
+
/// }
};
@@ -283,6 +289,9 @@ public:
/// The OS version we are targeting.
mutable VersionTuple TargetVersion;
+ /// The information about the darwin SDK that was used.
+ mutable Optional<DarwinSDKInfo> SDKInfo;
+
CudaInstallationDetector CudaInstallation;
private:
@@ -418,7 +427,7 @@ protected:
Action::OffloadKind DeviceOffloadKind) const override;
StringRef getPlatformFamily() const;
- StringRef getOSLibraryNameSuffix() const;
+ StringRef getOSLibraryNameSuffix(bool IgnoreSim = false) const override;
public:
static StringRef getSDKName(StringRef isysroot);
@@ -489,6 +498,10 @@ public:
void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
+ void AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
diff --git a/lib/Driver/ToolChains/FreeBSD.cpp b/lib/Driver/ToolChains/FreeBSD.cpp
index c16eabf06961..7a176d260aee 100644
--- a/lib/Driver/ToolChains/FreeBSD.cpp
+++ b/lib/Driver/ToolChains/FreeBSD.cpp
@@ -12,11 +12,11 @@
#include "Arch/Mips.h"
#include "Arch/Sparc.h"
#include "CommonArgs.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Support/VirtualFileSystem.h"
using namespace clang::driver;
using namespace clang::driver::tools;
diff --git a/lib/Driver/ToolChains/Fuchsia.cpp b/lib/Driver/ToolChains/Fuchsia.cpp
index 54c34ff159b1..de2c7411c5e4 100644
--- a/lib/Driver/ToolChains/Fuchsia.cpp
+++ b/lib/Driver/ToolChains/Fuchsia.cpp
@@ -76,10 +76,11 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
else if (Args.hasArg(options::OPT_shared))
CmdArgs.push_back("-shared");
+ const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs();
+
if (!Args.hasArg(options::OPT_shared)) {
std::string Dyld = D.DyldPrefix;
- if (ToolChain.getSanitizerArgs().needsAsanRt() &&
- ToolChain.getSanitizerArgs().needsSharedRt())
+ if (SanArgs.needsAsanRt() && SanArgs.needsSharedRt())
Dyld += "asan/";
Dyld += "ld.so.1";
CmdArgs.push_back("-dynamic-linker");
@@ -98,6 +99,8 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_L);
Args.AddAllArgs(CmdArgs, options::OPT_u);
+ addSanitizerPathLibArgs(ToolChain, Args, CmdArgs);
+
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
if (D.isUsingLTO()) {
@@ -106,8 +109,8 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
D.getLTOMode() == LTOK_Thin);
}
- addSanitizerRuntimes(ToolChain, Args, CmdArgs);
-
+ bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
+ bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
ToolChain.addProfileRTLibs(Args, CmdArgs);
@@ -119,15 +122,24 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (ToolChain.ShouldLinkCXXStdlib(Args)) {
bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
!Args.hasArg(options::OPT_static);
+ CmdArgs.push_back("--push-state");
+ CmdArgs.push_back("--as-needed");
if (OnlyLibstdcxxStatic)
CmdArgs.push_back("-Bstatic");
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
if (OnlyLibstdcxxStatic)
CmdArgs.push_back("-Bdynamic");
+ CmdArgs.push_back("-lm");
+ CmdArgs.push_back("--pop-state");
}
- CmdArgs.push_back("-lm");
}
+ if (NeedsSanitizerDeps)
+ linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
+
+ if (NeedsXRayDeps)
+ linkXRayRuntimeDeps(ToolChain, CmdArgs);
+
AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
if (Args.hasArg(options::OPT_pthread) ||
diff --git a/lib/Driver/ToolChains/Gnu.cpp b/lib/Driver/ToolChains/Gnu.cpp
index 3755673250b2..2ad45097dce8 100644
--- a/lib/Driver/ToolChains/Gnu.cpp
+++ b/lib/Driver/ToolChains/Gnu.cpp
@@ -16,7 +16,6 @@
#include "Arch/SystemZ.h"
#include "CommonArgs.h"
#include "Linux.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Config/config.h" // for GCC_INSTALL_PREFIX
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
@@ -27,6 +26,7 @@
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TargetParser.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <system_error>
using namespace clang::driver;
@@ -228,6 +228,30 @@ void tools::gcc::Linker::RenderExtraToolArgs(const JobAction &JA,
// The types are (hopefully) good enough.
}
+// On Arm the endianness of the output file is determined by the target and
+// can be overridden by the pseudo-target flags '-mlittle-endian'/'-EL' and
+// '-mbig-endian'/'-EB'. Unlike other targets the flag does not result in a
+// normalized triple so we must handle the flag here.
+static bool isArmBigEndian(const llvm::Triple &Triple,
+ const ArgList &Args) {
+ bool IsBigEndian = false;
+ switch (Triple.getArch()) {
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumbeb:
+ IsBigEndian = true;
+ LLVM_FALLTHROUGH;
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
+ options::OPT_mbig_endian))
+ IsBigEndian = !A->getOption().matches(options::OPT_mlittle_endian);
+ break;
+ default:
+ break;
+ }
+ return IsBigEndian;
+}
+
static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
switch (T.getArch()) {
case llvm::Triple::x86:
@@ -237,13 +261,12 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
case llvm::Triple::aarch64:
return "aarch64linux";
case llvm::Triple::aarch64_be:
- return "aarch64_be_linux";
+ return "aarch64linuxb";
case llvm::Triple::arm:
case llvm::Triple::thumb:
- return "armelf_linux_eabi";
case llvm::Triple::armeb:
case llvm::Triple::thumbeb:
- return "armelfb_linux_eabi";
+ return isArmBigEndian(T, Args) ? "armelfb_linux_eabi" : "armelf_linux_eabi";
case llvm::Triple::ppc:
return "elf32ppclinux";
case llvm::Triple::ppc64:
@@ -264,11 +287,13 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
case llvm::Triple::mipsel:
return "elf32ltsmip";
case llvm::Triple::mips64:
- if (tools::mips::hasMipsAbiArg(Args, "n32"))
+ if (tools::mips::hasMipsAbiArg(Args, "n32") ||
+ T.getEnvironment() == llvm::Triple::GNUABIN32)
return "elf32btsmipn32";
return "elf64btsmip";
case llvm::Triple::mips64el:
- if (tools::mips::hasMipsAbiArg(Args, "n32"))
+ if (tools::mips::hasMipsAbiArg(Args, "n32") ||
+ T.getEnvironment() == llvm::Triple::GNUABIN32)
return "elf32ltsmipn32";
return "elf64ltsmip";
case llvm::Triple::systemz:
@@ -323,14 +348,6 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// handled somewhere else.
Args.ClaimAllArgs(options::OPT_w);
- const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
- if (llvm::sys::path::stem(Exec) == "lld") {
- CmdArgs.push_back("-flavor");
- CmdArgs.push_back("old-gnu");
- CmdArgs.push_back("-target");
- CmdArgs.push_back(Args.MakeArgString(getToolChain().getTripleString()));
- }
-
if (!D.SysRoot.empty())
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
@@ -343,8 +360,13 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_s))
CmdArgs.push_back("-s");
- if (Arch == llvm::Triple::armeb || Arch == llvm::Triple::thumbeb)
- arm::appendEBLinkFlags(Args, CmdArgs, Triple);
+ if (Triple.isARM() || Triple.isThumb() || Triple.isAArch64()) {
+ bool IsBigEndian = isArmBigEndian(Triple, Args);
+ if (IsBigEndian)
+ arm::appendBE8LinkFlag(Args, CmdArgs, Triple);
+ IsBigEndian = IsBigEndian || Arch == llvm::Triple::aarch64_be;
+ CmdArgs.push_back(IsBigEndian ? "-EB" : "-EL");
+ }
// Most Android ARM64 targets should enable the linker fix for erratum
// 843419. Only non-Cortex-A53 devices are allowed to skip this flag.
@@ -539,6 +561,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
AddHIPLinkerScript(getToolChain(), C, Output, Inputs, Args, CmdArgs, JA,
*this);
+ const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
@@ -645,6 +668,7 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
case llvm::Triple::thumb:
case llvm::Triple::thumbeb: {
const llvm::Triple &Triple2 = getToolChain().getTriple();
+ CmdArgs.push_back(isArmBigEndian(Triple2, Args) ? "-EB" : "-EL");
switch (Triple2.getSubArch()) {
case llvm::Triple::ARMSubArch_v7:
CmdArgs.push_back("-mfpu=neon");
@@ -677,6 +701,8 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
}
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be: {
+ CmdArgs.push_back(
+ getToolChain().getArch() == llvm::Triple::aarch64_be ? "-EB" : "-EL");
Args.AddLastArg(CmdArgs, options::OPT_march_EQ);
normalizeCPUNamesForAssembler(Args, CmdArgs);
@@ -791,17 +817,17 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
if (Args.hasArg(options::OPT_gsplit_dwarf) &&
getToolChain().getTriple().isOSLinux())
SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
- SplitDebugName(Args, Inputs[0]));
+ SplitDebugName(Args, Output));
}
namespace {
// Filter to remove Multilibs that don't exist as a suffix to Path
class FilterNonExistent {
StringRef Base, File;
- vfs::FileSystem &VFS;
+ llvm::vfs::FileSystem &VFS;
public:
- FilterNonExistent(StringRef Base, StringRef File, vfs::FileSystem &VFS)
+ FilterNonExistent(StringRef Base, StringRef File, llvm::vfs::FileSystem &VFS)
: Base(Base), File(File), VFS(VFS) {}
bool operator()(const Multilib &M) {
return !VFS.exists(Base + M.gccSuffix() + File);
@@ -852,6 +878,10 @@ static bool isRISCV(llvm::Triple::ArchType Arch) {
return Arch == llvm::Triple::riscv32 || Arch == llvm::Triple::riscv64;
}
+static bool isMSP430(llvm::Triple::ArchType Arch) {
+ return Arch == llvm::Triple::msp430;
+}
+
static Multilib makeMultilib(StringRef commonSuffix) {
return Multilib(commonSuffix, commonSuffix, commonSuffix);
}
@@ -947,7 +977,7 @@ static bool findMipsCsMultilibs(const Multilib::flags_list &Flags,
return false;
}
-static bool findMipsAndroidMultilibs(vfs::FileSystem &VFS, StringRef Path,
+static bool findMipsAndroidMultilibs(llvm::vfs::FileSystem &VFS, StringRef Path,
const Multilib::flags_list &Flags,
FilterNonExistent &NonExistent,
DetectedMultilibs &Result) {
@@ -1397,6 +1427,26 @@ static void findAndroidArmMultilibs(const Driver &D,
Result.Multilibs = AndroidArmMultilibs;
}
+static bool findMSP430Multilibs(const Driver &D,
+ const llvm::Triple &TargetTriple,
+ StringRef Path, const ArgList &Args,
+ DetectedMultilibs &Result) {
+ FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
+ Multilib MSP430Multilib = makeMultilib("/430");
+ // FIXME: when clang starts to support msp430x ISA additional logic
+ // to select between multilib must be implemented
+ // Multilib MSP430xMultilib = makeMultilib("/large");
+
+ Result.Multilibs.push_back(MSP430Multilib);
+ Result.Multilibs.FilterOut(NonExistent);
+
+ Multilib::flags_list Flags;
+ if (Result.Multilibs.select(Flags, Result.SelectedMultilib))
+ return true;
+
+ return false;
+}
+
static void findRISCVMultilibs(const Driver &D,
const llvm::Triple &TargetTriple, StringRef Path,
const ArgList &Args, DetectedMultilibs &Result) {
@@ -1625,10 +1675,18 @@ Generic_GCC::GCCVersion Generic_GCC::GCCVersion::Parse(StringRef VersionText) {
return GoodVersion;
}
-static llvm::StringRef getGCCToolchainDir(const ArgList &Args) {
+static llvm::StringRef getGCCToolchainDir(const ArgList &Args,
+ llvm::StringRef SysRoot) {
const Arg *A = Args.getLastArg(clang::driver::options::OPT_gcc_toolchain);
if (A)
return A->getValue();
+
+ // If we have a SysRoot, ignore GCC_INSTALL_PREFIX.
+ // GCC_INSTALL_PREFIX specifies the gcc installation for the default
+ // sysroot and is likely not valid with a different sysroot.
+ if (!SysRoot.empty())
+ return "";
+
return GCC_INSTALL_PREFIX;
}
@@ -1660,7 +1718,7 @@ void Generic_GCC::GCCInstallationDetector::init(
SmallVector<std::string, 8> Prefixes(D.PrefixDirs.begin(),
D.PrefixDirs.end());
- StringRef GCCToolchainDir = getGCCToolchainDir(Args);
+ StringRef GCCToolchainDir = getGCCToolchainDir(Args, D.SysRoot);
if (GCCToolchainDir != "") {
if (GCCToolchainDir.back() == '/')
GCCToolchainDir = GCCToolchainDir.drop_back(); // remove the /
@@ -1769,9 +1827,10 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
std::string PrefixDir = SysRoot.str() + "/usr/gcc";
std::error_code EC;
- for (vfs::directory_iterator LI = D.getVFS().dir_begin(PrefixDir, EC), LE;
+ for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(PrefixDir, EC),
+ LE;
!EC && LI != LE; LI = LI.increment(EC)) {
- StringRef VersionText = llvm::sys::path::filename(LI->getName());
+ StringRef VersionText = llvm::sys::path::filename(LI->path());
GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);
// Filter out obviously bad entries.
@@ -1812,19 +1871,21 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
static const char *const AArch64LibDirs[] = {"/lib64", "/lib"};
static const char *const AArch64Triples[] = {
"aarch64-none-linux-gnu", "aarch64-linux-gnu", "aarch64-redhat-linux",
- "aarch64-suse-linux"};
+ "aarch64-suse-linux", "aarch64-linux-android"};
static const char *const AArch64beLibDirs[] = {"/lib"};
static const char *const AArch64beTriples[] = {"aarch64_be-none-linux-gnu",
"aarch64_be-linux-gnu"};
static const char *const ARMLibDirs[] = {"/lib"};
- static const char *const ARMTriples[] = {"arm-linux-gnueabi"};
+ static const char *const ARMTriples[] = {"arm-linux-gnueabi",
+ "arm-linux-androideabi"};
static const char *const ARMHFTriples[] = {"arm-linux-gnueabihf",
"armv7hl-redhat-linux-gnueabi",
"armv6hl-suse-linux-gnueabi",
"armv7hl-suse-linux-gnueabi"};
static const char *const ARMebLibDirs[] = {"/lib"};
- static const char *const ARMebTriples[] = {"armeb-linux-gnueabi"};
+ static const char *const ARMebTriples[] = {"armeb-linux-gnueabi",
+ "armeb-linux-androideabi"};
static const char *const ARMebHFTriples[] = {
"armeb-linux-gnueabihf", "armebv7hl-redhat-linux-gnueabi"};
@@ -1835,32 +1896,47 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
"x86_64-redhat-linux", "x86_64-suse-linux",
"x86_64-manbo-linux-gnu", "x86_64-linux-gnu",
"x86_64-slackware-linux", "x86_64-unknown-linux",
- "x86_64-amazon-linux"};
+ "x86_64-amazon-linux", "x86_64-linux-android"};
static const char *const X32LibDirs[] = {"/libx32"};
static const char *const X86LibDirs[] = {"/lib32", "/lib"};
static const char *const X86Triples[] = {
"i686-linux-gnu", "i686-pc-linux-gnu", "i486-linux-gnu",
"i386-linux-gnu", "i386-redhat-linux6E", "i686-redhat-linux",
"i586-redhat-linux", "i386-redhat-linux", "i586-suse-linux",
- "i486-slackware-linux", "i686-montavista-linux", "i586-linux-gnu"};
+ "i486-slackware-linux", "i686-montavista-linux", "i586-linux-gnu",
+ "i686-linux-android", "i386-gnu", "i486-gnu",
+ "i586-gnu", "i686-gnu"};
static const char *const MIPSLibDirs[] = {"/lib"};
- static const char *const MIPSTriples[] = {"mips-linux-gnu", "mips-mti-linux",
- "mips-mti-linux-gnu",
- "mips-img-linux-gnu"};
+ static const char *const MIPSTriples[] = {
+ "mips-linux-gnu", "mips-mti-linux", "mips-mti-linux-gnu",
+ "mips-img-linux-gnu", "mipsisa32r6-linux-gnu"};
static const char *const MIPSELLibDirs[] = {"/lib"};
- static const char *const MIPSELTriples[] = {"mipsel-linux-gnu",
- "mips-img-linux-gnu"};
+ static const char *const MIPSELTriples[] = {
+ "mipsel-linux-gnu", "mips-img-linux-gnu", "mipsisa32r6el-linux-gnu",
+ "mipsel-linux-android"};
static const char *const MIPS64LibDirs[] = {"/lib64", "/lib"};
static const char *const MIPS64Triples[] = {
- "mips64-linux-gnu", "mips-mti-linux-gnu", "mips-img-linux-gnu",
- "mips64-linux-gnuabi64"};
+ "mips64-linux-gnu", "mips-mti-linux-gnu",
+ "mips-img-linux-gnu", "mips64-linux-gnuabi64",
+ "mipsisa64r6-linux-gnu", "mipsisa64r6-linux-gnuabi64"};
static const char *const MIPS64ELLibDirs[] = {"/lib64", "/lib"};
static const char *const MIPS64ELTriples[] = {
- "mips64el-linux-gnu", "mips-mti-linux-gnu", "mips-img-linux-gnu",
- "mips64el-linux-gnuabi64"};
+ "mips64el-linux-gnu", "mips-mti-linux-gnu",
+ "mips-img-linux-gnu", "mips64el-linux-gnuabi64",
+ "mipsisa64r6el-linux-gnu", "mipsisa64r6el-linux-gnuabi64",
+ "mips64el-linux-android"};
+
+ static const char *const MIPSN32LibDirs[] = {"/lib32"};
+ static const char *const MIPSN32Triples[] = {"mips64-linux-gnuabin32",
+ "mipsisa64r6-linux-gnuabin32"};
+ static const char *const MIPSN32ELLibDirs[] = {"/lib32"};
+ static const char *const MIPSN32ELTriples[] = {
+ "mips64el-linux-gnuabin32", "mipsisa64r6el-linux-gnuabin32"};
+ static const char *const MSP430LibDirs[] = {"/lib"};
+ static const char *const MSP430Triples[] = {"msp430-elf"};
static const char *const PPCLibDirs[] = {"/lib32", "/lib"};
static const char *const PPCTriples[] = {
@@ -2057,6 +2133,8 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
TripleAliases.append(begin(MIPSTriples), end(MIPSTriples));
BiarchLibDirs.append(begin(MIPS64LibDirs), end(MIPS64LibDirs));
BiarchTripleAliases.append(begin(MIPS64Triples), end(MIPS64Triples));
+ BiarchLibDirs.append(begin(MIPSN32LibDirs), end(MIPSN32LibDirs));
+ BiarchTripleAliases.append(begin(MIPSN32Triples), end(MIPSN32Triples));
break;
case llvm::Triple::mipsel:
LibDirs.append(begin(MIPSELLibDirs), end(MIPSELLibDirs));
@@ -2064,20 +2142,30 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
TripleAliases.append(begin(MIPSTriples), end(MIPSTriples));
BiarchLibDirs.append(begin(MIPS64ELLibDirs), end(MIPS64ELLibDirs));
BiarchTripleAliases.append(begin(MIPS64ELTriples), end(MIPS64ELTriples));
+ BiarchLibDirs.append(begin(MIPSN32ELLibDirs), end(MIPSN32ELLibDirs));
+ BiarchTripleAliases.append(begin(MIPSN32ELTriples), end(MIPSN32ELTriples));
break;
case llvm::Triple::mips64:
LibDirs.append(begin(MIPS64LibDirs), end(MIPS64LibDirs));
TripleAliases.append(begin(MIPS64Triples), end(MIPS64Triples));
BiarchLibDirs.append(begin(MIPSLibDirs), end(MIPSLibDirs));
BiarchTripleAliases.append(begin(MIPSTriples), end(MIPSTriples));
+ BiarchLibDirs.append(begin(MIPSN32LibDirs), end(MIPSN32LibDirs));
+ BiarchTripleAliases.append(begin(MIPSN32Triples), end(MIPSN32Triples));
break;
case llvm::Triple::mips64el:
LibDirs.append(begin(MIPS64ELLibDirs), end(MIPS64ELLibDirs));
TripleAliases.append(begin(MIPS64ELTriples), end(MIPS64ELTriples));
BiarchLibDirs.append(begin(MIPSELLibDirs), end(MIPSELLibDirs));
BiarchTripleAliases.append(begin(MIPSELTriples), end(MIPSELTriples));
+ BiarchLibDirs.append(begin(MIPSN32ELLibDirs), end(MIPSN32ELLibDirs));
+ BiarchTripleAliases.append(begin(MIPSN32ELTriples), end(MIPSN32ELTriples));
BiarchTripleAliases.append(begin(MIPSTriples), end(MIPSTriples));
break;
+ case llvm::Triple::msp430:
+ LibDirs.append(begin(MSP430LibDirs), end(MSP430LibDirs));
+ TripleAliases.append(begin(MSP430Triples), end(MSP430Triples));
+ break;
case llvm::Triple::ppc:
LibDirs.append(begin(PPCLibDirs), end(PPCLibDirs));
TripleAliases.append(begin(PPCTriples), end(PPCTriples));
@@ -2149,6 +2237,8 @@ bool Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs(
return false;
} else if (isRISCV(TargetArch)) {
findRISCVMultilibs(D, TargetTriple, Path, Args, Detected);
+ } else if (isMSP430(TargetArch)) {
+ findMSP430Multilibs(D, TargetTriple, Path, Args, Detected);
} else if (!findBiarchMultilibs(D, TargetTriple, Path, Args,
NeedsBiarchSuffix, Detected)) {
return false;
@@ -2204,6 +2294,9 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
// triple.
{"i386-linux-gnu/gcc/" + CandidateTriple.str(), "../../..",
(TargetArch == llvm::Triple::x86 &&
+ TargetTriple.getOS() != llvm::Triple::Solaris)},
+ {"i386-gnu/gcc/" + CandidateTriple.str(), "../../..",
+ (TargetArch == llvm::Triple::x86 &&
TargetTriple.getOS() != llvm::Triple::Solaris)}};
for (auto &Suffix : Suffixes) {
@@ -2212,21 +2305,21 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
StringRef LibSuffix = Suffix.LibSuffix;
std::error_code EC;
- for (vfs::directory_iterator
+ for (llvm::vfs::directory_iterator
LI = D.getVFS().dir_begin(LibDir + "/" + LibSuffix, EC),
LE;
!EC && LI != LE; LI = LI.increment(EC)) {
- StringRef VersionText = llvm::sys::path::filename(LI->getName());
+ StringRef VersionText = llvm::sys::path::filename(LI->path());
GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);
if (CandidateVersion.Major != -1) // Filter obviously bad entries.
- if (!CandidateGCCInstallPaths.insert(LI->getName()).second)
+ if (!CandidateGCCInstallPaths.insert(LI->path()).second)
continue; // Saw this path before; no need to look at it again.
if (CandidateVersion.isOlderThan(4, 1, 1))
continue;
if (CandidateVersion <= Version)
continue;
- if (!ScanGCCForMultilibs(TargetTriple, Args, LI->getName(),
+ if (!ScanGCCForMultilibs(TargetTriple, Args, LI->path(),
NeedsBiarchSuffix))
continue;
@@ -2375,7 +2468,7 @@ bool Generic_GCC::isPICDefault() const {
case llvm::Triple::x86_64:
return getTriple().isOSWindows();
case llvm::Triple::ppc64:
- case llvm::Triple::ppc64le:
+ // Big endian PPC is PIC by default
return !getTriple().isOSBinFormatMachO() && !getTriple().isMacOSX();
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
@@ -2412,16 +2505,14 @@ bool Generic_GCC::IsIntegratedAssemblerDefault() const {
case llvm::Triple::systemz:
case llvm::Triple::mips:
case llvm::Triple::mipsel:
- return true;
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
- // Enabled for Debian, Android, FreeBSD and OpenBSD mips64/mipsel, as they
- // can precisely identify the ABI in use (Debian) or only use N64 for MIPS64
- // (Android). Other targets are unable to distinguish N32 from N64.
- if (getTriple().getEnvironment() == llvm::Triple::GNUABI64 ||
- getTriple().isAndroid() ||
- getTriple().isOSFreeBSD() ||
- getTriple().isOSOpenBSD())
+ case llvm::Triple::msp430:
+ return true;
+ case llvm::Triple::sparc:
+ case llvm::Triple::sparcel:
+ case llvm::Triple::sparcv9:
+ if (getTriple().isOSSolaris() || getTriple().isOSOpenBSD())
return true;
return false;
default:
@@ -2546,7 +2637,7 @@ void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs,
bool UseInitArrayDefault =
getTriple().getArch() == llvm::Triple::aarch64 ||
getTriple().getArch() == llvm::Triple::aarch64_be ||
- (getTriple().getOS() == llvm::Triple::FreeBSD &&
+ (getTriple().isOSFreeBSD() &&
getTriple().getOSMajorVersion() >= 12) ||
(getTriple().getOS() == llvm::Triple::Linux &&
((!GCCInstallation.isValid() || !V.isOlderThan(4, 7, 0)) ||
@@ -2554,7 +2645,9 @@ void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs,
getTriple().getOS() == llvm::Triple::NaCl ||
(getTriple().getVendor() == llvm::Triple::MipsTechnologies &&
!getTriple().hasEnvironment()) ||
- getTriple().getOS() == llvm::Triple::Solaris;
+ 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))
diff --git a/lib/Driver/ToolChains/HIP.cpp b/lib/Driver/ToolChains/HIP.cpp
index 03acf45a9b31..868765cf88e5 100644
--- a/lib/Driver/ToolChains/HIP.cpp
+++ b/lib/Driver/ToolChains/HIP.cpp
@@ -24,6 +24,12 @@ using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;
+#if _WIN32 || _WIN64
+#define NULL_FILE "nul"
+#else
+#define NULL_FILE "/dev/null"
+#endif
+
namespace {
static void addBCLib(Compilation &C, const ArgList &Args,
@@ -81,8 +87,8 @@ const char *AMDGCN::Linker::constructLLVMLinkCommand(
else
FlushDenormalControlBC = "oclc_daz_opt_off.amdgcn.bc";
- BCLibs.append({"opencl.amdgcn.bc",
- "ocml.amdgcn.bc", "ockl.amdgcn.bc", "irif.amdgcn.bc",
+ BCLibs.append({"hip.amdgcn.bc", "opencl.amdgcn.bc",
+ "ocml.amdgcn.bc", "ockl.amdgcn.bc",
"oclc_finite_only_off.amdgcn.bc",
FlushDenormalControlBC,
"oclc_correctly_rounded_sqrt_on.amdgcn.bc",
@@ -154,7 +160,7 @@ const char *AMDGCN::Linker::constructLlcCommand(
llvm::StringRef OutputFilePrefix, const char *InputFileName) const {
// Construct llc command.
ArgStringList LlcArgs{InputFileName, "-mtriple=amdgcn-amd-amdhsa",
- "-filetype=obj",
+ "-filetype=obj", "-mattr=-code-object-v3",
Args.MakeArgString("-mcpu=" + SubArchName), "-o"};
std::string LlcOutputFileName =
C.getDriver().GetTemporaryPath(OutputFilePrefix, "o");
@@ -184,6 +190,40 @@ void AMDGCN::Linker::constructLldCommand(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Lld, LldArgs, Inputs));
}
+// Construct a clang-offload-bundler command to bundle code objects for
+// different GPU's into a HIP fat binary.
+void AMDGCN::constructHIPFatbinCommand(Compilation &C, const JobAction &JA,
+ StringRef OutputFileName, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &Args, const Tool& T) {
+ // Construct clang-offload-bundler command to bundle object files for
+ // for different GPU archs.
+ ArgStringList BundlerArgs;
+ BundlerArgs.push_back(Args.MakeArgString("-type=o"));
+
+ // ToDo: Remove the dummy host binary entry which is required by
+ // clang-offload-bundler.
+ std::string BundlerTargetArg = "-targets=host-x86_64-unknown-linux";
+ std::string BundlerInputArg = "-inputs=" NULL_FILE;
+
+ for (const auto &II : Inputs) {
+ const auto* A = II.getAction();
+ BundlerTargetArg = BundlerTargetArg + ",hip-amdgcn-amd-amdhsa-" +
+ StringRef(A->getOffloadingArch()).str();
+ BundlerInputArg = BundlerInputArg + "," + II.getFilename();
+ }
+ BundlerArgs.push_back(Args.MakeArgString(BundlerTargetArg));
+ BundlerArgs.push_back(Args.MakeArgString(BundlerInputArg));
+
+ auto BundlerOutputArg =
+ Args.MakeArgString(std::string("-outputs=").append(OutputFileName));
+ BundlerArgs.push_back(BundlerOutputArg);
+
+ SmallString<128> BundlerPath(C.getDriver().Dir);
+ llvm::sys::path::append(BundlerPath, "clang-offload-bundler");
+ const char *Bundler = Args.MakeArgString(BundlerPath);
+ C.addCommand(llvm::make_unique<Command>(JA, T, Bundler, BundlerArgs, Inputs));
+}
+
// For amdgcn the inputs of the linker job are device bitcode and output is
// object file. It calls llvm-link, opt, llc, then lld steps.
void AMDGCN::Linker::ConstructJob(Compilation &C, const JobAction &JA,
@@ -192,6 +232,9 @@ void AMDGCN::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const ArgList &Args,
const char *LinkingOutput) const {
+ if (JA.getType() == types::TY_HIP_FATBIN)
+ return constructHIPFatbinCommand(C, JA, Output.getFilename(), Inputs, Args, *this);
+
assert(getToolChain().getTriple().getArch() == llvm::Triple::amdgcn &&
"Unsupported target");
@@ -244,9 +287,15 @@ void HIPToolChain::addClangTargetOptions(
options::OPT_fno_cuda_approx_transcendentals, false))
CC1Args.push_back("-fcuda-approx-transcendentals");
- if (DriverArgs.hasFlag(options::OPT_fcuda_rdc, options::OPT_fno_cuda_rdc,
+ if (DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
false))
- CC1Args.push_back("-fcuda-rdc");
+ CC1Args.push_back("-fgpu-rdc");
+
+ // Default to "hidden" visibility, as object level linking will not be
+ // supported for the foreseeable future.
+ if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
+ options::OPT_fvisibility_ms_compat))
+ CC1Args.append({"-fvisibility", "hidden"});
}
llvm::opt::DerivedArgList *
diff --git a/lib/Driver/ToolChains/HIP.h b/lib/Driver/ToolChains/HIP.h
index 40c9128e2f59..3af19d44dae0 100644
--- a/lib/Driver/ToolChains/HIP.h
+++ b/lib/Driver/ToolChains/HIP.h
@@ -19,6 +19,11 @@ namespace driver {
namespace tools {
namespace AMDGCN {
+ // Construct command for creating HIP fatbin.
+ void constructHIPFatbinCommand(Compilation &C, const JobAction &JA,
+ StringRef OutputFileName, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs, const Tool& T);
+
// Runs llvm-link/opt/llc/lld, which links multiple LLVM bitcode, together with
// device library, then compiles it to ISA in a shared object.
class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
diff --git a/lib/Driver/ToolChains/Hexagon.cpp b/lib/Driver/ToolChains/Hexagon.cpp
index c2b27b6d9ac6..d302a3e24d8b 100644
--- a/lib/Driver/ToolChains/Hexagon.cpp
+++ b/lib/Driver/ToolChains/Hexagon.cpp
@@ -8,9 +8,8 @@
//===----------------------------------------------------------------------===//
#include "Hexagon.h"
-#include "InputInfo.h"
#include "CommonArgs.h"
-#include "clang/Basic/VirtualFileSystem.h"
+#include "InputInfo.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
@@ -19,6 +18,7 @@
#include "llvm/Option/ArgList.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/VirtualFileSystem.h"
using namespace clang::driver;
using namespace clang::driver::tools;
@@ -32,6 +32,7 @@ static StringRef getDefaultHvxLength(StringRef Cpu) {
.Case("v60", "64b")
.Case("v62", "64b")
.Case("v65", "64b")
+ .Case("v66", "128b")
.Default("128b");
}
@@ -75,7 +76,7 @@ static void handleHVXTargetFeatures(const Driver &D, const ArgList &Args,
// Handle -mhvx-length=.
if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) {
- // These falgs are valid only if HVX in enabled.
+ // These flags are valid only if HVX in enabled.
if (!HasHVX)
D.Diag(diag::err_drv_invalid_hvx_length);
else if (A->getOption().matches(options::OPT_mhexagon_hvx_length_EQ))
@@ -369,9 +370,8 @@ void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA,
constructHexagonLinkArgs(C, JA, HTC, Output, Inputs, Args, CmdArgs,
LinkingOutput);
- std::string Linker = HTC.GetProgramPath("hexagon-link");
- C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
- CmdArgs, Inputs));
+ const char *Exec = Args.MakeArgString(HTC.GetLinkerPath());
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
// Hexagon tools end.
@@ -513,11 +513,6 @@ unsigned HexagonToolChain::getOptimizationLevel(
void HexagonToolChain::addClangTargetOptions(const ArgList &DriverArgs,
ArgStringList &CC1Args,
Action::OffloadKind) const {
- if (!DriverArgs.hasArg(options::OPT_ffp_contract)) {
- unsigned OptLevel = getOptimizationLevel(DriverArgs);
- if (OptLevel >= 3)
- CC1Args.push_back("-ffp-contract=fast");
- }
if (DriverArgs.hasArg(options::OPT_ffixed_r19)) {
CC1Args.push_back("-target-feature");
CC1Args.push_back("+reserved-r19");
diff --git a/lib/Driver/ToolChains/Hexagon.h b/lib/Driver/ToolChains/Hexagon.h
index e43b8a5b8800..a9e599de7ae5 100644
--- a/lib/Driver/ToolChains/Hexagon.h
+++ b/lib/Driver/ToolChains/Hexagon.h
@@ -81,6 +81,9 @@ public:
void addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+
+ const char *getDefaultLinker() const override { return "hexagon-link"; }
+
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
StringRef GetGCCLibAndIncVersion() const { return GCCLibAndIncVersion.Text; }
diff --git a/lib/Driver/ToolChains/Hurd.cpp b/lib/Driver/ToolChains/Hurd.cpp
new file mode 100644
index 000000000000..ff7b685dae3f
--- /dev/null
+++ b/lib/Driver/ToolChains/Hurd.cpp
@@ -0,0 +1,169 @@
+//===--- Hurd.cpp - Hurd ToolChain Implementations --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Hurd.h"
+#include "CommonArgs.h"
+#include "clang/Config/config.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/Options.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/VirtualFileSystem.h"
+
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
+using namespace clang;
+using namespace llvm::opt;
+
+using tools::addPathIfExists;
+
+/// Get our best guess at the multiarch triple for a target.
+///
+/// Debian-based systems are starting to use a multiarch setup where they use
+/// 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) {
+ 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
+ // 32-bit and 64-bit targets. Multiarch fixes its install triples to these
+ // regardless of what the actual target triple is.
+ if (D.getVFS().exists(SysRoot + "/lib/i386-gnu"))
+ return "i386-gnu";
+ }
+
+ // For most architectures, just use whatever we have rather than trying to be
+ // clever.
+ return TargetTriple.str();
+}
+
+static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
+ // It happens that only x86 and PPC use the 'lib32' variant of oslibdir, and
+ // using that variant while targeting other architectures causes problems
+ // because the libraries are laid out in shared system roots that can't cope
+ // with a 'lib32' library search path being considered. So we only enable
+ // them when we know we may need it.
+ //
+ // FIXME: This is a bit of a hack. We should really unify this code for
+ // reasoning about oslibdir spellings with the lib dir spellings in the
+ // GCCInstallationDetector, but that is a more significant refactoring.
+
+ if (Triple.getArch() == llvm::Triple::x86)
+ return "lib32";
+
+ return Triple.isArch32Bit() ? "lib" : "lib64";
+}
+
+Hurd::Hurd(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
+ std::string SysRoot = computeSysRoot();
+ path_list &Paths = getFilePaths();
+
+ const std::string OSLibDir = getOSLibDir(Triple, Args);
+ const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot);
+
+ // 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
+ // directory ('Dir' below) or the ResourceDir.
+ if (StringRef(D.Dir).startswith(SysRoot)) {
+ addPathIfExists(D, D.Dir + "/../lib/" + MultiarchTriple, Paths);
+ addPathIfExists(D, D.Dir + "/../" + OSLibDir, Paths);
+ }
+
+ addPathIfExists(D, SysRoot + "/lib/" + MultiarchTriple, Paths);
+ addPathIfExists(D, SysRoot + "/lib/../" + OSLibDir, Paths);
+
+ addPathIfExists(D, SysRoot + "/usr/lib/" + MultiarchTriple, Paths);
+ addPathIfExists(D, SysRoot + "/usr/lib/../" + OSLibDir, Paths);
+
+ // If we are currently running Clang inside of the requested system root, add
+ // its parent library path to those searched.
+ // FIXME: It's not clear whether we should use the driver's installed
+ // directory ('Dir' below) or the ResourceDir.
+ if (StringRef(D.Dir).startswith(SysRoot))
+ addPathIfExists(D, D.Dir + "/../lib", Paths);
+
+ addPathIfExists(D, SysRoot + "/lib", Paths);
+ addPathIfExists(D, SysRoot + "/usr/lib", Paths);
+}
+
+bool Hurd::HasNativeLLVMSupport() const { return true; }
+
+Tool *Hurd::buildLinker() const { return new tools::gnutools::Linker(*this); }
+
+Tool *Hurd::buildAssembler() const {
+ return new tools::gnutools::Assembler(*this);
+}
+
+std::string Hurd::computeSysRoot() const {
+ if (!getDriver().SysRoot.empty())
+ return getDriver().SysRoot;
+
+ return std::string();
+}
+
+std::string Hurd::getDynamicLinker(const ArgList &Args) const {
+ if (getArch() == llvm::Triple::x86)
+ return "/lib/ld.so";
+
+ llvm_unreachable("unsupported architecture");
+}
+
+void Hurd::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ const Driver &D = getDriver();
+ std::string SysRoot = computeSysRoot();
+
+ if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
+ return;
+
+ if (!DriverArgs.hasArg(options::OPT_nostdlibinc))
+ addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include");
+
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+ SmallString<128> P(D.ResourceDir);
+ llvm::sys::path::append(P, "include");
+ addSystemInclude(DriverArgs, CC1Args, P);
+ }
+
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+
+ // Check for configure-time C include directories.
+ StringRef CIncludeDirs(C_INCLUDE_DIRS);
+ if (CIncludeDirs != "") {
+ SmallVector<StringRef, 5> Dirs;
+ CIncludeDirs.split(Dirs, ":");
+ for (StringRef Dir : Dirs) {
+ StringRef Prefix =
+ llvm::sys::path::is_absolute(Dir) ? StringRef(SysRoot) : "";
+ addExternCSystemInclude(DriverArgs, CC1Args, Prefix + Dir);
+ }
+ return;
+ }
+
+ // Lacking those, try to detect the correct set of system includes for the
+ // target triple.
+ if (getTriple().getArch() == llvm::Triple::x86) {
+ std::string Path = SysRoot + "/usr/include/i386-gnu";
+ if (D.getVFS().exists(Path))
+ addExternCSystemInclude(DriverArgs, CC1Args, Path);
+ }
+
+ // Add an include of '/include' directly. This isn't provided by default by
+ // system GCCs, but is often used with cross-compiling GCCs, and harmless to
+ // add even when Clang is acting as-if it were a system compiler.
+ addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include");
+
+ addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
+}
diff --git a/lib/Driver/ToolChains/Hurd.h b/lib/Driver/ToolChains/Hurd.h
new file mode 100644
index 000000000000..d14619f0e2ce
--- /dev/null
+++ b/lib/Driver/ToolChains/Hurd.h
@@ -0,0 +1,46 @@
+//===--- Hurd.h - Hurd ToolChain Implementations ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Hurd_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Hurd_H
+
+#include "Gnu.h"
+#include "clang/Driver/ToolChain.h"
+
+namespace clang {
+namespace driver {
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY Hurd : public Generic_ELF {
+public:
+ Hurd(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ bool HasNativeLLVMSupport() const override;
+
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
+ virtual std::string computeSysRoot() const;
+
+ virtual std::string getDynamicLinker(const llvm::opt::ArgList &Args) const;
+
+ std::vector<std::string> ExtraOpts;
+
+protected:
+ Tool *buildAssembler() const override;
+ Tool *buildLinker() const override;
+};
+
+} // end namespace toolchains
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Hurd_H
diff --git a/lib/Driver/ToolChains/Linux.cpp b/lib/Driver/ToolChains/Linux.cpp
index f8f36239180c..65ab9b2daf54 100644
--- a/lib/Driver/ToolChains/Linux.cpp
+++ b/lib/Driver/ToolChains/Linux.cpp
@@ -13,7 +13,6 @@
#include "Arch/PPC.h"
#include "Arch/RISCV.h"
#include "CommonArgs.h"
-#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Config/config.h"
#include "clang/Driver/Distro.h"
#include "clang/Driver/Driver.h"
@@ -23,6 +22,7 @@
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <system_error>
using namespace clang::driver;
@@ -44,6 +44,7 @@ static std::string getMultiarchTriple(const Driver &D,
llvm::Triple::EnvironmentType TargetEnvironment =
TargetTriple.getEnvironment();
bool IsAndroid = TargetTriple.isAndroid();
+ bool IsMipsR6 = TargetTriple.getSubArch() == llvm::Triple::MipsSubArch_r6;
// For most architectures, just use whatever we have rather than trying to be
// clever.
@@ -101,30 +102,36 @@ static std::string getMultiarchTriple(const Driver &D,
if (D.getVFS().exists(SysRoot + "/lib/aarch64_be-linux-gnu"))
return "aarch64_be-linux-gnu";
break;
- case llvm::Triple::mips:
- if (D.getVFS().exists(SysRoot + "/lib/mips-linux-gnu"))
- return "mips-linux-gnu";
+ case llvm::Triple::mips: {
+ std::string Arch = IsMipsR6 ? "mipsisa32r6" : "mips";
+ if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-gnu"))
+ return Arch + "-linux-gnu";
break;
- case llvm::Triple::mipsel:
+ }
+ case llvm::Triple::mipsel: {
if (IsAndroid)
return "mipsel-linux-android";
- if (D.getVFS().exists(SysRoot + "/lib/mipsel-linux-gnu"))
- return "mipsel-linux-gnu";
+ std::string Arch = IsMipsR6 ? "mipsisa32r6el" : "mipsel";
+ if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-gnu"))
+ return Arch + "-linux-gnu";
break;
- case llvm::Triple::mips64:
- if (D.getVFS().exists(SysRoot + "/lib/mips64-linux-gnu"))
- return "mips64-linux-gnu";
- if (D.getVFS().exists(SysRoot + "/lib/mips64-linux-gnuabi64"))
- return "mips64-linux-gnuabi64";
+ }
+ case llvm::Triple::mips64: {
+ std::string Arch = IsMipsR6 ? "mipsisa64r6" : "mips64";
+ std::string ABI = llvm::Triple::getEnvironmentTypeName(TargetEnvironment);
+ if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-" + ABI))
+ return Arch + "-linux-" + ABI;
break;
- case llvm::Triple::mips64el:
+ }
+ case llvm::Triple::mips64el: {
if (IsAndroid)
return "mips64el-linux-android";
- if (D.getVFS().exists(SysRoot + "/lib/mips64el-linux-gnu"))
- return "mips64el-linux-gnu";
- if (D.getVFS().exists(SysRoot + "/lib/mips64el-linux-gnuabi64"))
- return "mips64el-linux-gnuabi64";
+ std::string Arch = IsMipsR6 ? "mipsisa64r6el" : "mips64el";
+ std::string ABI = llvm::Triple::getEnvironmentTypeName(TargetEnvironment);
+ if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-" + ABI))
+ return Arch + "-linux-" + ABI;
break;
+ }
case llvm::Triple::ppc:
if (D.getVFS().exists(SysRoot + "/lib/powerpc-linux-gnuspe"))
return "powerpc-linux-gnuspe";
@@ -210,6 +217,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
GCCInstallation.init(Triple, Args);
Multilibs = GCCInstallation.getMultilibs();
+ SelectedMultilib = GCCInstallation.getMultilib();
llvm::Triple::ArchType Arch = Triple.getArch();
std::string SysRoot = computeSysRoot();
@@ -228,16 +236,25 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
Distro Distro(D.getVFS());
- if (Distro.IsAlpineLinux()) {
+ if (Distro.IsAlpineLinux() || Triple.isAndroid()) {
ExtraOpts.push_back("-z");
ExtraOpts.push_back("now");
}
- if (Distro.IsOpenSUSE() || Distro.IsUbuntu() || Distro.IsAlpineLinux()) {
+ if (Distro.IsOpenSUSE() || Distro.IsUbuntu() || Distro.IsAlpineLinux() ||
+ Triple.isAndroid()) {
ExtraOpts.push_back("-z");
ExtraOpts.push_back("relro");
}
+ // The lld default page size is too large for Aarch64, which produces much
+ // larger .so files and images for arm64 device targets. Use 4KB page size
+ // for Android arm64 targets instead.
+ if (Triple.isAArch64() && Triple.isAndroid()) {
+ ExtraOpts.push_back("-z");
+ ExtraOpts.push_back("max-page-size=4096");
+ }
+
if (GCCInstallation.getParentLibPath().find("opt/rh/devtoolset") !=
StringRef::npos)
// With devtoolset on RHEL, we want to add a bin directory that is relative
@@ -263,15 +280,18 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// and the MIPS ABI require .dynsym to be sorted in different ways.
// .gnu.hash needs symbols to be grouped by hash code whereas the MIPS
// ABI requires a mapping between the GOT and the symbol table.
- // Android loader does not support .gnu.hash.
+ // Android loader does not support .gnu.hash until API 23.
// Hexagon linker/loader does not support .gnu.hash
- if (!IsMips && !IsAndroid && !IsHexagon) {
+ if (!IsMips && !IsHexagon) {
if (Distro.IsRedhat() || Distro.IsOpenSUSE() || Distro.IsAlpineLinux() ||
- (Distro.IsUbuntu() && Distro >= Distro::UbuntuMaverick))
+ (Distro.IsUbuntu() && Distro >= Distro::UbuntuMaverick) ||
+ (IsAndroid && !Triple.isAndroidVersionLT(23)))
ExtraOpts.push_back("--hash-style=gnu");
- if (Distro.IsDebian() || Distro.IsOpenSUSE() || Distro == Distro::UbuntuLucid ||
- Distro == Distro::UbuntuJaunty || Distro == Distro::UbuntuKarmic)
+ if (Distro.IsDebian() || Distro.IsOpenSUSE() ||
+ Distro == Distro::UbuntuLucid || Distro == Distro::UbuntuJaunty ||
+ Distro == Distro::UbuntuKarmic ||
+ (IsAndroid && Triple.isAndroidVersionLT(23)))
ExtraOpts.push_back("--hash-style=both");
}
@@ -299,16 +319,14 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
if (GCCInstallation.isValid()) {
const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
const std::string &LibPath = GCCInstallation.getParentLibPath();
- const Multilib &Multilib = GCCInstallation.getMultilib();
- const MultilibSet &Multilibs = GCCInstallation.getMultilibs();
// Add toolchain / multilib specific file paths.
- addMultilibsFilePaths(D, Multilibs, Multilib,
+ addMultilibsFilePaths(D, Multilibs, SelectedMultilib,
GCCInstallation.getInstallPath(), Paths);
// Sourcery CodeBench MIPS toolchain holds some libraries under
// a biarch-like suffix of the GCC installation.
- addPathIfExists(D, GCCInstallation.getInstallPath() + Multilib.gccSuffix(),
+ addPathIfExists(D, GCCInstallation.getInstallPath() + SelectedMultilib.gccSuffix(),
Paths);
// GCC cross compiling toolchains will install target libraries which ship
@@ -330,7 +348,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// Note that this matches the GCC behavior. See the below comment for where
// Clang diverges from GCC's behavior.
addPathIfExists(D, LibPath + "/../" + GCCTriple.str() + "/lib/../" +
- OSLibDir + Multilib.osSuffix(),
+ OSLibDir + SelectedMultilib.osSuffix(),
Paths);
// If the GCC installation we found is inside of the sysroot, we want to
@@ -433,6 +451,12 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
addPathIfExists(D, SysRoot + "/usr/lib", Paths);
}
+ToolChain::CXXStdlibType Linux::GetDefaultCXXStdlibType() const {
+ if (getTriple().isAndroid())
+ return ToolChain::CST_Libcxx;
+ return ToolChain::CST_Libstdcxx;
+}
+
bool Linux::HasNativeLLVMSupport() const { return true; }
Tool *Linux::buildLinker() const { return new tools::gnutools::Linker(*this); }
@@ -695,12 +719,28 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
const StringRef MIPSELMultiarchIncludeDirs[] = {
"/usr/include/mipsel-linux-gnu"};
const StringRef MIPS64MultiarchIncludeDirs[] = {
- "/usr/include/mips64-linux-gnu", "/usr/include/mips64-linux-gnuabi64"};
+ "/usr/include/mips64-linux-gnuabi64"};
const StringRef MIPS64ELMultiarchIncludeDirs[] = {
- "/usr/include/mips64el-linux-gnu",
"/usr/include/mips64el-linux-gnuabi64"};
+ const StringRef MIPSN32MultiarchIncludeDirs[] = {
+ "/usr/include/mips64-linux-gnuabin32"};
+ const StringRef MIPSN32ELMultiarchIncludeDirs[] = {
+ "/usr/include/mips64el-linux-gnuabin32"};
+ const StringRef MIPSR6MultiarchIncludeDirs[] = {
+ "/usr/include/mipsisa32-linux-gnu"};
+ const StringRef MIPSR6ELMultiarchIncludeDirs[] = {
+ "/usr/include/mipsisa32r6el-linux-gnu"};
+ const StringRef MIPS64R6MultiarchIncludeDirs[] = {
+ "/usr/include/mipsisa64r6-linux-gnuabi64"};
+ const StringRef MIPS64R6ELMultiarchIncludeDirs[] = {
+ "/usr/include/mipsisa64r6el-linux-gnuabi64"};
+ const StringRef MIPSN32R6MultiarchIncludeDirs[] = {
+ "/usr/include/mipsisa64r6-linux-gnuabin32"};
+ const StringRef MIPSN32R6ELMultiarchIncludeDirs[] = {
+ "/usr/include/mipsisa64r6el-linux-gnuabin32"};
const StringRef PPCMultiarchIncludeDirs[] = {
- "/usr/include/powerpc-linux-gnu"};
+ "/usr/include/powerpc-linux-gnu",
+ "/usr/include/powerpc-linux-gnuspe"};
const StringRef PPC64MultiarchIncludeDirs[] = {
"/usr/include/powerpc64-linux-gnu"};
const StringRef PPC64LEMultiarchIncludeDirs[] = {
@@ -738,16 +778,38 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
MultiarchIncludeDirs = ARMEBMultiarchIncludeDirs;
break;
case llvm::Triple::mips:
- MultiarchIncludeDirs = MIPSMultiarchIncludeDirs;
+ if (getTriple().getSubArch() == llvm::Triple::MipsSubArch_r6)
+ MultiarchIncludeDirs = MIPSR6MultiarchIncludeDirs;
+ else
+ MultiarchIncludeDirs = MIPSMultiarchIncludeDirs;
break;
case llvm::Triple::mipsel:
- MultiarchIncludeDirs = MIPSELMultiarchIncludeDirs;
+ if (getTriple().getSubArch() == llvm::Triple::MipsSubArch_r6)
+ MultiarchIncludeDirs = MIPSR6ELMultiarchIncludeDirs;
+ else
+ MultiarchIncludeDirs = MIPSELMultiarchIncludeDirs;
break;
case llvm::Triple::mips64:
- MultiarchIncludeDirs = MIPS64MultiarchIncludeDirs;
+ if (getTriple().getSubArch() == llvm::Triple::MipsSubArch_r6)
+ if (getTriple().getEnvironment() == llvm::Triple::GNUABIN32)
+ MultiarchIncludeDirs = MIPSN32R6MultiarchIncludeDirs;
+ else
+ MultiarchIncludeDirs = MIPS64R6MultiarchIncludeDirs;
+ else if (getTriple().getEnvironment() == llvm::Triple::GNUABIN32)
+ MultiarchIncludeDirs = MIPSN32MultiarchIncludeDirs;
+ else
+ MultiarchIncludeDirs = MIPS64MultiarchIncludeDirs;
break;
case llvm::Triple::mips64el:
- MultiarchIncludeDirs = MIPS64ELMultiarchIncludeDirs;
+ if (getTriple().getSubArch() == llvm::Triple::MipsSubArch_r6)
+ if (getTriple().getEnvironment() == llvm::Triple::GNUABIN32)
+ MultiarchIncludeDirs = MIPSN32R6ELMultiarchIncludeDirs;
+ else
+ MultiarchIncludeDirs = MIPS64R6ELMultiarchIncludeDirs;
+ else if (getTriple().getEnvironment() == llvm::Triple::GNUABIN32)
+ MultiarchIncludeDirs = MIPSN32ELMultiarchIncludeDirs;
+ else
+ MultiarchIncludeDirs = MIPS64ELMultiarchIncludeDirs;
break;
case llvm::Triple::ppc:
MultiarchIncludeDirs = PPCMultiarchIncludeDirs;
@@ -876,6 +938,9 @@ void Linux::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
// Freescale SDK C++ headers are directly in <sysroot>/usr/include/c++,
// without a subdirectory corresponding to the gcc version.
LibDir.str() + "/../include/c++",
+ // Cray's gcc installation puts headers under "g++" without a
+ // version suffix.
+ LibDir.str() + "/../include/g++",
};
for (const auto &IncludePath : LibStdCXXIncludePathCandidates) {
@@ -907,6 +972,12 @@ bool Linux::isPIEDefault() const {
getTriple().isMusl() || getSanitizerArgs().requiresPIE();
}
+bool Linux::IsMathErrnoDefault() const {
+ if (getTriple().isAndroid())
+ return false;
+ return Generic_ELF::IsMathErrnoDefault();
+}
+
SanitizerMask Linux::getSupportedSanitizers() const {
const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
@@ -934,6 +1005,8 @@ SanitizerMask Linux::getSupportedSanitizers() const {
Res |= SanitizerKind::Leak;
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64)
Res |= SanitizerKind::Thread;
+ if (IsX86_64)
+ Res |= SanitizerKind::KernelMemory;
if (IsX86_64 || IsMIPS64)
Res |= SanitizerKind::Efficiency;
if (IsX86 || IsX86_64)
@@ -954,7 +1027,7 @@ void Linux::addProfileRTLibs(const llvm::opt::ArgList &Args,
// Add linker option -u__llvm_runtime_variable to cause runtime
// initialization module to be linked in.
- if (!Args.hasArg(options::OPT_coverage))
+ if ((!Args.hasArg(options::OPT_coverage)) && (!Args.hasArg(options::OPT_ftest_coverage)))
CmdArgs.push_back(Args.MakeArgString(
Twine("-u", llvm::getInstrProfRuntimeHookVarName())));
ToolChain::addProfileRTLibs(Args, CmdArgs);
diff --git a/lib/Driver/ToolChains/Linux.h b/lib/Driver/ToolChains/Linux.h
index 22dbbecf6b96..4a662cb4b427 100644
--- a/lib/Driver/ToolChains/Linux.h
+++ b/lib/Driver/ToolChains/Linux.h
@@ -37,7 +37,9 @@ public:
llvm::opt::ArgStringList &CC1Args) const override;
void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+ CXXStdlibType GetDefaultCXXStdlibType() const override;
bool isPIEDefault() const override;
+ bool IsMathErrnoDefault() const override;
SanitizerMask getSupportedSanitizers() const override;
void addProfileRTLibs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
diff --git a/lib/Driver/ToolChains/MSP430.cpp b/lib/Driver/ToolChains/MSP430.cpp
new file mode 100644
index 000000000000..b2ff88dbd021
--- /dev/null
+++ b/lib/Driver/ToolChains/MSP430.cpp
@@ -0,0 +1,233 @@
+//===--- MSP430.cpp - MSP430 Helpers for Tools ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MSP430.h"
+#include "CommonArgs.h"
+#include "Gnu.h"
+#include "InputInfo.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Multilib.h"
+#include "clang/Driver/Options.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+static bool isSupportedMCU(const StringRef MCU) {
+ return llvm::StringSwitch<bool>(MCU)
+#define MSP430_MCU(NAME) .Case(NAME, true)
+#include "clang/Basic/MSP430Target.def"
+ .Default(false);
+}
+
+static StringRef getSupportedHWMult(const Arg *MCU) {
+ if (!MCU)
+ return "none";
+
+ return llvm::StringSwitch<StringRef>(MCU->getValue())
+#define MSP430_MCU_FEAT(NAME, HWMULT) .Case(NAME, HWMULT)
+#include "clang/Basic/MSP430Target.def"
+ .Default("none");
+}
+
+static StringRef getHWMultLib(const ArgList &Args) {
+ StringRef HWMult = Args.getLastArgValue(options::OPT_mhwmult_EQ, "auto");
+ if (HWMult == "auto") {
+ HWMult = getSupportedHWMult(Args.getLastArg(options::OPT_mmcu_EQ));
+ }
+
+ return llvm::StringSwitch<StringRef>(HWMult)
+ .Case("16bit", "-lmul_16")
+ .Case("32bit", "-lmul_32")
+ .Case("f5series", "-lmul_f5")
+ .Default("-lmul_none");
+}
+
+void msp430::getMSP430TargetFeatures(const Driver &D, const ArgList &Args,
+ std::vector<StringRef> &Features) {
+ const Arg *MCU = Args.getLastArg(options::OPT_mmcu_EQ);
+ if (MCU && !isSupportedMCU(MCU->getValue())) {
+ D.Diag(diag::err_drv_clang_unsupported) << MCU->getValue();
+ return;
+ }
+
+ const Arg *HWMultArg = Args.getLastArg(options::OPT_mhwmult_EQ);
+ if (!MCU && !HWMultArg)
+ return;
+
+ StringRef HWMult = HWMultArg ? HWMultArg->getValue() : "auto";
+ StringRef SupportedHWMult = getSupportedHWMult(MCU);
+
+ if (HWMult == "auto") {
+ // 'auto' - deduce hw multiplier support based on mcu name provided.
+ // If no mcu name is provided, assume no hw multiplier is supported.
+ if (!MCU)
+ D.Diag(clang::diag::warn_drv_msp430_hwmult_no_device);
+ HWMult = SupportedHWMult;
+ }
+
+ if (HWMult == "none") {
+ // 'none' - disable hw multiplier.
+ Features.push_back("-hwmult16");
+ Features.push_back("-hwmult32");
+ Features.push_back("-hwmultf5");
+ return;
+ }
+
+ if (MCU && SupportedHWMult == "none")
+ D.Diag(clang::diag::warn_drv_msp430_hwmult_unsupported) << HWMult;
+ if (MCU && HWMult != SupportedHWMult)
+ D.Diag(clang::diag::warn_drv_msp430_hwmult_mismatch)
+ << SupportedHWMult << HWMult;
+
+ if (HWMult == "16bit") {
+ // '16bit' - for 16-bit only hw multiplier.
+ Features.push_back("+hwmult16");
+ } else if (HWMult == "32bit") {
+ // '32bit' - for 16/32-bit hw multiplier.
+ Features.push_back("+hwmult32");
+ } else if (HWMult == "f5series") {
+ // 'f5series' - for 16/32-bit hw multiplier supported by F5 series mcus.
+ Features.push_back("+hwmultf5");
+ } else {
+ D.Diag(clang::diag::err_drv_unsupported_option_argument)
+ << HWMultArg->getAsString(Args) << HWMult;
+ }
+}
+
+/// MSP430 Toolchain
+MSP430ToolChain::MSP430ToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
+
+ StringRef MultilibSuf = "";
+
+ GCCInstallation.init(Triple, Args);
+ if (GCCInstallation.isValid()) {
+ MultilibSuf = GCCInstallation.getMultilib().gccSuffix();
+
+ SmallString<128> GCCBinPath;
+ llvm::sys::path::append(GCCBinPath,
+ GCCInstallation.getParentLibPath(), "..", "bin");
+ addPathIfExists(D, GCCBinPath, getProgramPaths());
+
+ SmallString<128> GCCRtPath;
+ llvm::sys::path::append(GCCRtPath,
+ GCCInstallation.getInstallPath(), MultilibSuf);
+ addPathIfExists(D, GCCRtPath, getFilePaths());
+ }
+
+ SmallString<128> SysRootDir(computeSysRoot());
+ llvm::sys::path::append(SysRootDir, "lib", MultilibSuf);
+ addPathIfExists(D, SysRootDir, getFilePaths());
+}
+
+std::string MSP430ToolChain::computeSysRoot() const {
+ if (!getDriver().SysRoot.empty())
+ return getDriver().SysRoot;
+
+ SmallString<128> Dir;
+ if (GCCInstallation.isValid())
+ llvm::sys::path::append(Dir, GCCInstallation.getParentLibPath(), "..",
+ GCCInstallation.getTriple().str());
+ else
+ llvm::sys::path::append(Dir, getDriver().Dir, "..", getTriple().str());
+
+ return Dir.str();
+}
+
+void MSP430ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdinc) ||
+ DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+
+ SmallString<128> Dir(computeSysRoot());
+ llvm::sys::path::append(Dir, "include");
+ addSystemInclude(DriverArgs, CC1Args, Dir.str());
+}
+
+void MSP430ToolChain::addClangTargetOptions(const ArgList &DriverArgs,
+ ArgStringList &CC1Args,
+ Action::OffloadKind) const {
+ CC1Args.push_back("-nostdsysteminc");
+
+ const auto *MCUArg = DriverArgs.getLastArg(options::OPT_mmcu_EQ);
+ if (!MCUArg)
+ return;
+
+ const StringRef MCU = MCUArg->getValue();
+ if (MCU.startswith("msp430i")) {
+ // 'i' should be in lower case as it's defined in TI MSP430-GCC headers
+ CC1Args.push_back(DriverArgs.MakeArgString(
+ "-D__MSP430i" + MCU.drop_front(7).upper() + "__"));
+ } else {
+ CC1Args.push_back(DriverArgs.MakeArgString("-D__" + MCU.upper() + "__"));
+ }
+}
+
+Tool *MSP430ToolChain::buildLinker() const {
+ return new tools::msp430::Linker(*this);
+}
+
+void msp430::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const ToolChain &ToolChain = getToolChain();
+ const Driver &D = ToolChain.getDriver();
+ std::string Linker = ToolChain.GetProgramPath(getShortName());
+ ArgStringList CmdArgs;
+
+ if (!D.SysRoot.empty())
+ CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ ToolChain.AddFilePathLibArgs(Args, CmdArgs);
+
+ if (!Args.hasArg(options::OPT_T)) {
+ if (const Arg *MCUArg = Args.getLastArg(options::OPT_mmcu_EQ))
+ CmdArgs.push_back(
+ Args.MakeArgString("-T" + StringRef(MCUArg->getValue()) + ".ld"));
+ } else {
+ Args.AddAllArgs(CmdArgs, options::OPT_T);
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o")));
+ }
+
+ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
+
+ CmdArgs.push_back("--start-group");
+ CmdArgs.push_back(Args.MakeArgString(getHWMultLib(Args)));
+ CmdArgs.push_back("-lgcc");
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ CmdArgs.push_back("-lc");
+ CmdArgs.push_back("-lcrt");
+ CmdArgs.push_back("-lnosys");
+ }
+ CmdArgs.push_back("--end-group");
+
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
+ }
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
+ CmdArgs, Inputs));
+}
diff --git a/lib/Driver/ToolChains/MSP430.h b/lib/Driver/ToolChains/MSP430.h
new file mode 100644
index 000000000000..0fdceb75b963
--- /dev/null
+++ b/lib/Driver/ToolChains/MSP430.h
@@ -0,0 +1,71 @@
+//===--- MSP430.h - MSP430-specific Tool Helpers ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MSP430_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MSP430_H
+
+#include "Gnu.h"
+#include "InputInfo.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Tool.h"
+#include "clang/Driver/ToolChain.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/Option.h"
+
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace driver {
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY MSP430ToolChain : public Generic_ELF {
+public:
+ MSP430ToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind) const override;
+
+protected:
+ Tool *buildLinker() const override;
+
+private:
+ std::string computeSysRoot() const;
+};
+
+} // end namespace toolchains
+
+namespace tools {
+namespace msp430 {
+
+class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
+public:
+ Linker(const ToolChain &TC)
+ : GnuTool("MSP430::Linker", "msp430-elf-ld", TC) {}
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
+void getMSP430TargetFeatures(const Driver &D, const llvm::opt::ArgList &Args,
+ std::vector<llvm::StringRef> &Features);
+} // end namespace msp430
+} // end namespace tools
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MSP430_H
diff --git a/lib/Driver/ToolChains/MSVC.cpp b/lib/Driver/ToolChains/MSVC.cpp
index d062c6abc955..7e34b0df5c8c 100644
--- a/lib/Driver/ToolChains/MSVC.cpp
+++ b/lib/Driver/ToolChains/MSVC.cpp
@@ -355,6 +355,15 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT__SLASH_Zd))
CmdArgs.push_back("-debug");
+ // Pass on /Brepro if it was passed to the compiler.
+ // Note that /Brepro maps to -mno-incremental-linker-compatible.
+ bool DefaultIncrementalLinkerCompatible =
+ C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment();
+ if (!Args.hasFlag(options::OPT_mincremental_linker_compatible,
+ options::OPT_mno_incremental_linker_compatible,
+ DefaultIncrementalLinkerCompatible))
+ CmdArgs.push_back("-Brepro");
+
bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd,
options::OPT_shared);
if (DLL) {
@@ -365,6 +374,17 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName));
}
+ if (TC.getSanitizerArgs().needsFuzzer()) {
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back(
+ Args.MakeArgString(std::string("-wholearchive:") +
+ TC.getCompilerRTArgString(Args, "fuzzer", false)));
+ CmdArgs.push_back(Args.MakeArgString("-debug"));
+ // Prevent the linker from padding sections we use for instrumentation
+ // arrays.
+ CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
+ }
+
if (TC.getSanitizerArgs().needsAsanRt()) {
CmdArgs.push_back(Args.MakeArgString("-debug"));
CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
@@ -702,15 +722,15 @@ bool MSVCToolChain::IsIntegratedAssemblerDefault() const {
}
bool MSVCToolChain::IsUnwindTablesDefault(const ArgList &Args) const {
- // Emit unwind tables by default on Win64. All non-x86_32 Windows platforms
- // such as ARM and PPC actually require unwind tables, but LLVM doesn't know
- // how to generate them yet.
-
// Don't emit unwind tables by default for MachO targets.
if (getTriple().isOSBinFormatMachO())
return false;
- return getArch() == llvm::Triple::x86_64;
+ // All non-x86_32 Windows targets require unwind tables. However, LLVM
+ // doesn't know how to generate them for all targets, so only enable
+ // the ones that are actually implemented.
+ return getArch() == llvm::Triple::x86_64 ||
+ getArch() == llvm::Triple::aarch64;
}
bool MSVCToolChain::isPICDefault() const {
@@ -1266,7 +1286,7 @@ VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D,
if (MSVT.empty() &&
Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
IsWindowsMSVC)) {
- // -fms-compatibility-version=19.11 is default, aka 2017
+ // -fms-compatibility-version=19.11 is default, aka 2017, 15.3
MSVT = VersionTuple(19, 11);
}
return MSVT;
@@ -1298,6 +1318,8 @@ MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
SanitizerMask Res = ToolChain::getSupportedSanitizers();
Res |= SanitizerKind::Address;
+ Res |= SanitizerKind::Fuzzer;
+ Res |= SanitizerKind::FuzzerNoLink;
Res &= ~SanitizerKind::CFIMFCall;
return Res;
}
@@ -1356,6 +1378,7 @@ static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL,
}
break;
case 'g':
+ A->claim();
break;
case 'i':
if (I + 1 != E && OptStr[I + 1] == '-') {
diff --git a/lib/Driver/ToolChains/MSVC.h b/lib/Driver/ToolChains/MSVC.h
index 1db589ec9706..ebca0018bb85 100644
--- a/lib/Driver/ToolChains/MSVC.h
+++ b/lib/Driver/ToolChains/MSVC.h
@@ -11,6 +11,7 @@
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MSVC_H
#include "Cuda.h"
+#include "clang/Basic/DebugInfoOptions.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
@@ -78,6 +79,18 @@ public:
bool isPIEDefault() const override;
bool isPICDefaultForced() const override;
+ /// Set CodeView as the default debug info format. Users can use -gcodeview
+ /// and -gdwarf to override the default.
+ codegenoptions::DebugInfoFormat getDefaultDebugFormat() const override {
+ return codegenoptions::DIF_CodeView;
+ }
+
+ /// Set the debugger tuning to "default", since we're definitely not tuning
+ /// for GDB.
+ llvm::DebuggerKind getDefaultDebuggerTuning() const override {
+ return llvm::DebuggerKind::Default;
+ }
+
enum class SubDirectoryType {
Bin,
Include,
diff --git a/lib/Driver/ToolChains/MinGW.cpp b/lib/Driver/ToolChains/MinGW.cpp
index a88e00f0c8e8..2d5217d03d3a 100644
--- a/lib/Driver/ToolChains/MinGW.cpp
+++ b/lib/Driver/ToolChains/MinGW.cpp
@@ -10,10 +10,12 @@
#include "MinGW.h"
#include "InputInfo.h"
#include "CommonArgs.h"
+#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
+#include "clang/Driver/SanitizerArgs.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -52,7 +54,7 @@ void tools::MinGW::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_gsplit_dwarf))
SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
- SplitDebugName(Args, Inputs[0]));
+ SplitDebugName(Args, Output));
}
void tools::MinGW::Linker::AddLibGCC(const ArgList &Args,
@@ -95,7 +97,7 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const char *LinkingOutput) const {
const ToolChain &TC = getToolChain();
const Driver &D = TC.getDriver();
- // const SanitizerArgs &Sanitize = TC.getSanitizerArgs();
+ const SanitizerArgs &Sanitize = TC.getSanitizerArgs();
ArgStringList CmdArgs;
@@ -187,8 +189,6 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
TC.AddFilePathLibArgs(Args, CmdArgs);
AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
- // TODO: Add ASan stuff here
-
// TODO: Add profile stuff here
if (TC.ShouldLinkCXXStdlib(Args)) {
@@ -220,8 +220,24 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lssp_nonshared");
CmdArgs.push_back("-lssp");
}
- if (Args.hasArg(options::OPT_fopenmp))
- CmdArgs.push_back("-lgomp");
+
+ if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
+ options::OPT_fno_openmp, false)) {
+ switch (TC.getDriver().getOpenMPRuntime(Args)) {
+ case Driver::OMPRT_OMP:
+ CmdArgs.push_back("-lomp");
+ break;
+ case Driver::OMPRT_IOMP5:
+ CmdArgs.push_back("-liomp5md");
+ break;
+ case Driver::OMPRT_GOMP:
+ CmdArgs.push_back("-lgomp");
+ break;
+ case Driver::OMPRT_Unknown:
+ // Already diagnosed.
+ break;
+ }
+ }
AddLibGCC(Args, CmdArgs);
@@ -231,6 +247,24 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_pthread))
CmdArgs.push_back("-lpthread");
+ if (Sanitize.needsAsanRt()) {
+ // MinGW always links against a shared MSVCRT.
+ CmdArgs.push_back(
+ TC.getCompilerRTArgString(Args, "asan_dynamic", true));
+ CmdArgs.push_back(
+ TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk"));
+ CmdArgs.push_back(Args.MakeArgString("--require-defined"));
+ CmdArgs.push_back(Args.MakeArgString(TC.getArch() == llvm::Triple::x86
+ ? "___asan_seh_interceptor"
+ : "__asan_seh_interceptor"));
+ // Make sure the linker consider all object files from the dynamic
+ // runtime thunk.
+ CmdArgs.push_back(Args.MakeArgString("--whole-archive"));
+ CmdArgs.push_back(Args.MakeArgString(
+ TC.getCompilerRT(Args, "asan_dynamic_runtime_thunk")));
+ CmdArgs.push_back(Args.MakeArgString("--no-whole-archive"));
+ }
+
if (!HasWindowsApp) {
// Add system libraries. If linking to libwindowsapp.a, that import
// library replaces all these and we shouldn't accidentally try to
@@ -359,6 +393,10 @@ toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple,
getFilePaths().push_back(Base + "lib");
// openSUSE
getFilePaths().push_back(Base + Arch + "/sys-root/mingw/lib");
+
+ NativeLLVMSupport =
+ Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER)
+ .equals_lower("lld");
}
bool toolchains::MinGW::IsIntegratedAssemblerDefault() const { return true; }
@@ -386,7 +424,17 @@ Tool *toolchains::MinGW::buildLinker() const {
return new tools::MinGW::Linker(*this);
}
+bool toolchains::MinGW::HasNativeLLVMSupport() const {
+ return NativeLLVMSupport;
+}
+
bool toolchains::MinGW::IsUnwindTablesDefault(const ArgList &Args) const {
+ Arg *ExceptionArg = Args.getLastArg(options::OPT_fsjlj_exceptions,
+ options::OPT_fseh_exceptions,
+ options::OPT_fdwarf_exceptions);
+ if (ExceptionArg &&
+ ExceptionArg->getOption().matches(options::OPT_fseh_exceptions))
+ return true;
return getArch() == llvm::Triple::x86_64;
}
@@ -407,6 +455,12 @@ toolchains::MinGW::GetExceptionModel(const ArgList &Args) const {
return llvm::ExceptionHandling::DwarfCFI;
}
+SanitizerMask toolchains::MinGW::getSupportedSanitizers() const {
+ SanitizerMask Res = ToolChain::getSupportedSanitizers();
+ Res |= SanitizerKind::Address;
+ return Res;
+}
+
void toolchains::MinGW::AddCudaIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
diff --git a/lib/Driver/ToolChains/MinGW.h b/lib/Driver/ToolChains/MinGW.h
index 0c3919d29f77..04d23006ee75 100644
--- a/lib/Driver/ToolChains/MinGW.h
+++ b/lib/Driver/ToolChains/MinGW.h
@@ -59,12 +59,16 @@ public:
MinGW(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
+ bool HasNativeLLVMSupport() const override;
+
bool IsIntegratedAssemblerDefault() const override;
bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override;
bool isPICDefault() const override;
bool isPIEDefault() const override;
bool isPICDefaultForced() const override;
+ SanitizerMask getSupportedSanitizers() const override;
+
llvm::ExceptionHandling GetExceptionModel(
const llvm::opt::ArgList &Args) const override;
@@ -97,6 +101,8 @@ private:
void findGccLibDir();
llvm::ErrorOr<std::string> findGcc();
llvm::ErrorOr<std::string> findClangRelativeSysroot();
+
+ bool NativeLLVMSupport;
};
} // end namespace toolchains
diff --git a/lib/Driver/ToolChains/Minix.cpp b/lib/Driver/ToolChains/Minix.cpp
index 39e6f90b6ef0..7fadcb129d46 100644
--- a/lib/Driver/ToolChains/Minix.cpp
+++ b/lib/Driver/ToolChains/Minix.cpp
@@ -8,13 +8,13 @@
//===----------------------------------------------------------------------===//
#include "Minix.h"
-#include "InputInfo.h"
#include "CommonArgs.h"
-#include "clang/Basic/VirtualFileSystem.h"
+#include "InputInfo.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Support/VirtualFileSystem.h"
using namespace clang::driver;
using namespace clang;
diff --git a/lib/Driver/ToolChains/MipsLinux.h b/lib/Driver/ToolChains/MipsLinux.h
index d4b476d883e6..edf58a62b95c 100644
--- a/lib/Driver/ToolChains/MipsLinux.h
+++ b/lib/Driver/ToolChains/MipsLinux.h
@@ -49,7 +49,7 @@ public:
}
const char *getDefaultLinker() const override {
- return "lld";
+ return "ld.lld";
}
private:
diff --git a/lib/Driver/ToolChains/NetBSD.cpp b/lib/Driver/ToolChains/NetBSD.cpp
index 02caafda1657..b1321cacaf7a 100644
--- a/lib/Driver/ToolChains/NetBSD.cpp
+++ b/lib/Driver/ToolChains/NetBSD.cpp
@@ -164,7 +164,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
break;
case llvm::Triple::armeb:
case llvm::Triple::thumbeb:
- arm::appendEBLinkFlags(Args, CmdArgs, ToolChain.getEffectiveTriple());
+ arm::appendBE8LinkFlag(Args, CmdArgs, ToolChain.getEffectiveTriple());
CmdArgs.push_back("-m");
switch (ToolChain.getTriple().getEnvironment()) {
case llvm::Triple::EABI:
@@ -448,12 +448,24 @@ SanitizerMask NetBSD::getSupportedSanitizers() const {
Res |= SanitizerKind::Vptr;
}
if (IsX86_64) {
+ Res |= SanitizerKind::DataFlow;
Res |= SanitizerKind::Efficiency;
Res |= SanitizerKind::Fuzzer;
Res |= SanitizerKind::FuzzerNoLink;
+ Res |= SanitizerKind::HWAddress;
Res |= SanitizerKind::KernelAddress;
+ Res |= SanitizerKind::KernelHWAddress;
+ Res |= SanitizerKind::KernelMemory;
Res |= SanitizerKind::Memory;
Res |= SanitizerKind::Thread;
}
return Res;
}
+
+void NetBSD::addClangTargetOptions(const ArgList &,
+ ArgStringList &CC1Args,
+ Action::OffloadKind) const {
+ const SanitizerArgs &SanArgs = getSanitizerArgs();
+ if (SanArgs.hasAnySanitizer())
+ CC1Args.push_back("-D_REENTRANT");
+}
diff --git a/lib/Driver/ToolChains/NetBSD.h b/lib/Driver/ToolChains/NetBSD.h
index 49e3a58d02c3..ae0865fd6573 100644
--- a/lib/Driver/ToolChains/NetBSD.h
+++ b/lib/Driver/ToolChains/NetBSD.h
@@ -76,6 +76,10 @@ 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/lib/Driver/ToolChains/OpenBSD.cpp b/lib/Driver/ToolChains/OpenBSD.cpp
index 7b98cd62bbfc..3d35d37b7db3 100644
--- a/lib/Driver/ToolChains/OpenBSD.cpp
+++ b/lib/Driver/ToolChains/OpenBSD.cpp
@@ -111,9 +111,9 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// handled somewhere else.
Args.ClaimAllArgs(options::OPT_w);
- if (getToolChain().getArch() == llvm::Triple::mips64)
+ if (ToolChain.getArch() == llvm::Triple::mips64)
CmdArgs.push_back("-EB");
- else if (getToolChain().getArch() == llvm::Triple::mips64el)
+ else if (ToolChain.getArch() == llvm::Triple::mips64el)
CmdArgs.push_back("-EL");
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) {
@@ -138,7 +138,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_pie))
CmdArgs.push_back("-pie");
- if (Args.hasArg(options::OPT_nopie))
+ if (Args.hasArg(options::OPT_nopie) || Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-nopie");
if (Output.isFilename()) {
@@ -149,44 +149,40 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ const char *crt0 = nullptr;
+ const char *crtbegin = nullptr;
if (!Args.hasArg(options::OPT_shared)) {
if (Args.hasArg(options::OPT_pg))
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("gcrt0.o")));
+ crt0 = "gcrt0.o";
else if (Args.hasArg(options::OPT_static) &&
!Args.hasArg(options::OPT_nopie))
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("rcrt0.o")));
+ crt0 = "rcrt0.o";
else
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crt0.o")));
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o")));
+ crt0 = "crt0.o";
+ crtbegin = "crtbegin.o";
} else {
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtbeginS.o")));
+ crtbegin = "crtbeginS.o";
}
- }
- std::string Triple = getToolChain().getTripleString();
- if (Triple.substr(0, 6) == "x86_64")
- Triple.replace(0, 6, "amd64");
- CmdArgs.push_back(
- Args.MakeArgString("-L/usr/lib/gcc-lib/" + Triple + "/4.2.1"));
- CmdArgs.push_back(Args.MakeArgString("-L/usr/lib"));
+ if (crt0)
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt0)));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
+ }
- Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
- options::OPT_e, options::OPT_s, options::OPT_t,
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ ToolChain.AddFilePathLibArgs(Args, CmdArgs);
+ Args.AddAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_e,
+ options::OPT_s, options::OPT_t,
options::OPT_Z_Flag, options::OPT_r});
bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
if (D.CCCIsCXX()) {
- if (getToolChain().ShouldLinkCXXStdlib(Args))
- getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+ if (ToolChain.ShouldLinkCXXStdlib(Args))
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-lm_p");
else
@@ -202,7 +198,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
// FIXME: For some reason GCC passes -lgcc before adding
// the default system libraries. Just mimic this for now.
- CmdArgs.push_back("-lgcc");
+ CmdArgs.push_back("-lcompiler_rt");
if (Args.hasArg(options::OPT_pthread)) {
if (!Args.hasArg(options::OPT_shared) && Args.hasArg(options::OPT_pg))
@@ -218,21 +214,22 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lc");
}
- CmdArgs.push_back("-lgcc");
+ CmdArgs.push_back("-lcompiler_rt");
}
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ const char *crtend = nullptr;
if (!Args.hasArg(options::OPT_shared))
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
+ crtend = "crtend.o";
else
- CmdArgs.push_back(
- Args.MakeArgString(getToolChain().GetFilePath("crtendS.o")));
+ crtend = "crtendS.o";
+
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
}
const char *Exec = Args.MakeArgString(
- !NeedsSanitizerDeps ? getToolChain().GetLinkerPath()
- : getToolChain().GetProgramPath("ld.lld"));
+ !NeedsSanitizerDeps ? ToolChain.GetLinkerPath()
+ : ToolChain.GetProgramPath("ld.lld"));
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
@@ -257,8 +254,7 @@ SanitizerMask OpenBSD::getSupportedSanitizers() const {
OpenBSD::OpenBSD(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
- getFilePaths().push_back(getDriver().Dir + "/../lib");
- getFilePaths().push_back("/usr/lib");
+ getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
}
void OpenBSD::AddCXXStdlibLibArgs(const ArgList &Args,
diff --git a/lib/Driver/ToolChains/OpenBSD.h b/lib/Driver/ToolChains/OpenBSD.h
index bf8dfa4653cb..1912abdb95bc 100644
--- a/lib/Driver/ToolChains/OpenBSD.h
+++ b/lib/Driver/ToolChains/OpenBSD.h
@@ -58,6 +58,14 @@ public:
bool IsMathErrnoDefault() const override { return false; }
bool IsObjCNonFragileABIDefault() const override { return true; }
bool isPIEDefault() const override { return true; }
+
+ RuntimeLibType GetDefaultRuntimeLibType() const override {
+ return ToolChain::RLT_CompilerRT;
+ }
+ CXXStdlibType GetDefaultCXXStdlibType() const override {
+ return ToolChain::CST_Libcxx;
+ }
+
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
diff --git a/lib/Driver/ToolChains/PS4CPU.cpp b/lib/Driver/ToolChains/PS4CPU.cpp
index a4b74d492331..0708d25fe45c 100644
--- a/lib/Driver/ToolChains/PS4CPU.cpp
+++ b/lib/Driver/ToolChains/PS4CPU.cpp
@@ -121,7 +121,8 @@ static void ConstructPS4LinkJob(const Tool &T, Compilation &C,
assert(Output.isNothing() && "Invalid output.");
}
- AddPS4SanitizerArgs(ToolChain, CmdArgs);
+ if(!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
+ AddPS4SanitizerArgs(ToolChain, CmdArgs);
Args.AddAllArgs(CmdArgs, options::OPT_L);
Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
@@ -190,7 +191,8 @@ static void ConstructGoldLinkJob(const Tool &T, Compilation &C,
assert(Output.isNothing() && "Invalid output.");
}
- AddPS4SanitizerArgs(ToolChain, CmdArgs);
+ if(!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
+ AddPS4SanitizerArgs(ToolChain, CmdArgs);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
const char *crt1 = nullptr;
diff --git a/lib/Driver/ToolChains/RISCV.cpp b/lib/Driver/ToolChains/RISCVToolchain.cpp
index 31996fc588f1..e787c82b28a8 100644
--- a/lib/Driver/ToolChains/RISCV.cpp
+++ b/lib/Driver/ToolChains/RISCVToolchain.cpp
@@ -1,4 +1,4 @@
-//===--- RISCV.cpp - RISCV ToolChain Implementations ------------*- C++ -*-===//
+//===--- RISCVToolchain.cpp - RISCV ToolChain Implementations ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,12 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#include "RISCV.h"
+#include "RISCVToolchain.h"
#include "CommonArgs.h"
#include "InputInfo.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
@@ -27,7 +28,7 @@ RISCVToolChain::RISCVToolChain(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
GCCInstallation.init(Triple, Args);
- getFilePaths().push_back(D.SysRoot + "/lib");
+ getFilePaths().push_back(computeSysRoot() + "/lib");
if (GCCInstallation.isValid()) {
getFilePaths().push_back(GCCInstallation.getInstallPath().str());
getProgramPaths().push_back(
@@ -39,13 +40,21 @@ Tool *RISCVToolChain::buildLinker() const {
return new tools::RISCV::Linker(*this);
}
+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,
ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdinc))
return;
if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
- SmallString<128> Dir(getDriver().SysRoot);
+ SmallString<128> Dir(computeSysRoot());
llvm::sys::path::append(Dir, "include");
addSystemInclude(DriverArgs, CC1Args, Dir.str());
}
@@ -54,15 +63,30 @@ void RISCVToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
void RISCVToolChain::addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
- StringRef LibDir = GCCInstallation.getParentLibPath();
const GCCVersion &Version = GCCInstallation.getVersion();
StringRef TripleStr = GCCInstallation.getTriple().str();
const Multilib &Multilib = GCCInstallation.getMultilib();
- addLibStdCXXIncludePaths(
- LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text,
+ addLibStdCXXIncludePaths(computeSysRoot() + "/include/c++/" + Version.Text,
"", TripleStr, "", "", Multilib.includeSuffix(), DriverArgs, CC1Args);
}
+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();
+
+ if (!llvm::sys::fs::exists(SysRootDir))
+ return std::string();
+
+ return SysRootDir;
+}
+
void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
diff --git a/lib/Driver/ToolChains/RISCV.h b/lib/Driver/ToolChains/RISCVToolchain.h
index 6f59d84020d8..4b38690b1b61 100644
--- a/lib/Driver/ToolChains/RISCV.h
+++ b/lib/Driver/ToolChains/RISCVToolchain.h
@@ -1,4 +1,4 @@
-//===--- RISCV.h - RISCV ToolChain Implementations --------------*- C++ -*-===//
+//===--- RISCVToolchain.h - RISCV ToolChain Implementations -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_RISCV_H
-#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_RISCV_H
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_RISCVTOOLCHAIN_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_RISCVTOOLCHAIN_H
#include "Gnu.h"
#include "clang/Driver/ToolChain.h"
@@ -23,6 +23,9 @@ public:
const llvm::opt::ArgList &Args);
bool IsIntegratedAssemblerDefault() const override { return true; }
+ void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind) const override;
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
@@ -32,6 +35,9 @@ public:
protected:
Tool *buildLinker() const override;
+
+private:
+ std::string computeSysRoot() const;
};
} // end namespace toolchains
@@ -54,4 +60,4 @@ public:
} // end namespace driver
} // end namespace clang
-#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_RISCV_H
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_RISCVTOOLCHAIN_H
diff --git a/lib/Driver/ToolChains/Solaris.h b/lib/Driver/ToolChains/Solaris.h
index 9e14269b393e..4d9c828b5c6b 100644
--- a/lib/Driver/ToolChains/Solaris.h
+++ b/lib/Driver/ToolChains/Solaris.h
@@ -55,8 +55,6 @@ public:
Solaris(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
- bool IsIntegratedAssemblerDefault() const override { return true; }
-
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
diff --git a/lib/Driver/ToolChains/WebAssembly.cpp b/lib/Driver/ToolChains/WebAssembly.cpp
index 94f7279bbdba..6310d5fabaec 100644
--- a/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/lib/Driver/ToolChains/WebAssembly.cpp
@@ -22,15 +22,20 @@ using namespace clang;
using namespace llvm::opt;
wasm::Linker::Linker(const ToolChain &TC)
- : GnuTool("wasm::Linker", "lld", TC) {}
-
-bool wasm::Linker::isLinkJob() const {
- return true;
+ : GnuTool("wasm::Linker", "lld", TC) {}
+
+/// Following the conventions in https://wiki.debian.org/Multiarch/Tuples,
+/// we remove the vendor field to form the multiarch triple.
+static std::string getMultiarchTriple(const Driver &D,
+ const llvm::Triple &TargetTriple,
+ StringRef SysRoot) {
+ return (TargetTriple.getArchName() + "-" +
+ TargetTriple.getOSAndEnvironmentName()).str();
}
-bool wasm::Linker::hasIntegratedCPP() const {
- return false;
-}
+bool wasm::Linker::isLinkJob() const { return true; }
+
+bool wasm::Linker::hasIntegratedCPP() const { return false; }
void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
@@ -41,8 +46,6 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const ToolChain &ToolChain = getToolChain();
const char *Linker = Args.MakeArgString(ToolChain.GetLinkerPath());
ArgStringList CmdArgs;
- CmdArgs.push_back("-flavor");
- CmdArgs.push_back("wasm");
if (Args.hasArg(options::OPT_s))
CmdArgs.push_back("--strip-all");
@@ -75,13 +78,23 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args)
- : ToolChain(D, Triple, Args) {
+ : ToolChain(D, Triple, Args) {
assert(Triple.isArch32Bit() != Triple.isArch64Bit());
getProgramPaths().push_back(getDriver().getInstalledDir());
- getFilePaths().push_back(getDriver().SysRoot + "/lib");
+ 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");
+ } else {
+ const std::string MultiarchTriple =
+ getMultiarchTriple(getDriver(), Triple, getDriver().SysRoot);
+ getFilePaths().push_back(getDriver().SysRoot + "/lib/" + MultiarchTriple);
+ }
}
bool WebAssembly::IsMathErrnoDefault() const { return false; }
@@ -117,7 +130,8 @@ ToolChain::RuntimeLibType WebAssembly::GetDefaultRuntimeLibType() const {
return ToolChain::RLT_CompilerRT;
}
-ToolChain::CXXStdlibType WebAssembly::GetCXXStdlibType(const ArgList &Args) const {
+ToolChain::CXXStdlibType
+WebAssembly::GetCXXStdlibType(const ArgList &Args) const {
if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
StringRef Value = A->getValue();
if (Value != "libc++")
@@ -129,16 +143,29 @@ ToolChain::CXXStdlibType WebAssembly::GetCXXStdlibType(const ArgList &Args) cons
void WebAssembly::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
- if (!DriverArgs.hasArg(options::OPT_nostdinc))
+ if (!DriverArgs.hasArg(options::OPT_nostdinc)) {
+ if (getTriple().getOS() != llvm::Triple::UnknownOS) {
+ const std::string MultiarchTriple =
+ getMultiarchTriple(getDriver(), getTriple(), getDriver().SysRoot);
+ addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/include/" + MultiarchTriple);
+ }
addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/include");
+ }
}
void WebAssembly::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (!DriverArgs.hasArg(options::OPT_nostdlibinc) &&
- !DriverArgs.hasArg(options::OPT_nostdincxx))
+ !DriverArgs.hasArg(options::OPT_nostdincxx)) {
+ if (getTriple().getOS() != llvm::Triple::UnknownOS) {
+ const std::string MultiarchTriple =
+ getMultiarchTriple(getDriver(), getTriple(), getDriver().SysRoot);
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/include/" + MultiarchTriple + "/c++/v1");
+ }
addSystemInclude(DriverArgs, CC1Args,
getDriver().SysRoot + "/include/c++/v1");
+ }
}
void WebAssembly::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
diff --git a/lib/Driver/ToolChains/WebAssembly.h b/lib/Driver/ToolChains/WebAssembly.h
index cdbb34ff919f..d795bad90020 100644
--- a/lib/Driver/ToolChains/WebAssembly.h
+++ b/lib/Driver/ToolChains/WebAssembly.h
@@ -51,14 +51,15 @@ private:
bool hasBlocksRuntime() const override;
bool SupportsProfiling() const override;
bool HasNativeLLVMSupport() const override;
- void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args,
- Action::OffloadKind DeviceOffloadKind) const override;
+ void
+ addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadKind) const override;
RuntimeLibType GetDefaultRuntimeLibType() const override;
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
- void AddClangSystemIncludeArgs(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
void AddClangCXXStdlibIncludeArgs(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
@@ -66,9 +67,7 @@ private:
llvm::opt::ArgStringList &CmdArgs) const override;
std::string getThreadModel() const override;
- const char *getDefaultLinker() const override {
- return "lld";
- }
+ const char *getDefaultLinker() const override { return "wasm-ld"; }
Tool *buildLinker() const override;
};
diff --git a/lib/Driver/Types.cpp b/lib/Driver/Types.cpp
index 45bb699cfb88..9d2737bbc719 100644
--- a/lib/Driver/Types.cpp
+++ b/lib/Driver/Types.cpp
@@ -312,9 +312,11 @@ ID types::lookupHeaderTypeForSourceType(ID Id) {
default:
return Id;
+ // FIXME: Handle preprocessed input types.
case types::TY_C:
return types::TY_CHeader;
case types::TY_CXX:
+ case types::TY_CXXModule:
return types::TY_CXXHeader;
case types::TY_ObjC:
return types::TY_ObjCHeader;
diff --git a/lib/Driver/XRayArgs.cpp b/lib/Driver/XRayArgs.cpp
index 30b0e72760c9..1a48493d7dc7 100644
--- a/lib/Driver/XRayArgs.cpp
+++ b/lib/Driver/XRayArgs.cpp
@@ -50,13 +50,23 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
D.Diag(diag::err_drv_clang_unsupported)
<< (std::string(XRayInstrumentOption) + " on " + Triple.str());
}
- } else if (Triple.getOS() == llvm::Triple::FreeBSD ||
- Triple.getOS() == llvm::Triple::OpenBSD ||
- Triple.getOS() == llvm::Triple::NetBSD) {
+ } else if (Triple.isOSFreeBSD() ||
+ Triple.isOSOpenBSD() ||
+ Triple.isOSNetBSD() ||
+ Triple.getOS() == llvm::Triple::Darwin) {
if (Triple.getArch() != llvm::Triple::x86_64) {
D.Diag(diag::err_drv_clang_unsupported)
<< (std::string(XRayInstrumentOption) + " on " + Triple.str());
}
+ } else if (Triple.getOS() == llvm::Triple::Fuchsia) {
+ switch (Triple.getArch()) {
+ case llvm::Triple::x86_64:
+ case llvm::Triple::aarch64:
+ break;
+ default:
+ D.Diag(diag::err_drv_clang_unsupported)
+ << (std::string(XRayInstrumentOption) + " on " + Triple.str());
+ }
} else {
D.Diag(diag::err_drv_clang_unsupported)
<< (std::string(XRayInstrumentOption) + " on " + Triple.str());
@@ -164,7 +174,7 @@ XRayArgs::XRayArgs(const ToolChain &TC, const ArgList &Args) {
}
// Then we want to sort and unique the modes we've collected.
- llvm::sort(Modes.begin(), Modes.end());
+ llvm::sort(Modes);
Modes.erase(std::unique(Modes.begin(), Modes.end()), Modes.end());
}
}
@@ -214,4 +224,19 @@ void XRayArgs::addArgs(const ToolChain &TC, const ArgList &Args,
ModeOpt += Mode;
CmdArgs.push_back(Args.MakeArgString(ModeOpt));
}
+
+ SmallString<64> Bundle("-fxray-instrumentation-bundle=");
+ if (InstrumentationBundle.full()) {
+ Bundle += "all";
+ } else if (InstrumentationBundle.empty()) {
+ Bundle += "none";
+ } else {
+ if (InstrumentationBundle.has(XRayInstrKind::Function))
+ Bundle += "function";
+ if (InstrumentationBundle.has(XRayInstrKind::Custom))
+ Bundle += "custom";
+ if (InstrumentationBundle.has(XRayInstrKind::Typed))
+ Bundle += "typed";
+ }
+ CmdArgs.push_back(Args.MakeArgString(Bundle));
}