aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Driver/ToolChain.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Driver/ToolChain.cpp')
-rw-r--r--clang/lib/Driver/ToolChain.cpp111
1 files changed, 82 insertions, 29 deletions
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 7a4319ea680f..bc70205a6c01 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -36,6 +36,7 @@
#include "llvm/Option/Option.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TargetParser.h"
#include "llvm/Support/VersionTuple.h"
@@ -88,6 +89,33 @@ ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
addIfExists(getFilePaths(), getArchSpecificLibPath());
}
+llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
+ToolChain::executeToolChainProgram(StringRef Executable) const {
+ llvm::SmallString<64> OutputFile;
+ llvm::sys::fs::createTemporaryFile("toolchain-program", "txt", OutputFile);
+ llvm::FileRemover OutputRemover(OutputFile.c_str());
+ std::optional<llvm::StringRef> Redirects[] = {
+ {""},
+ OutputFile.str(),
+ {""},
+ };
+
+ std::string ErrorMessage;
+ if (llvm::sys::ExecuteAndWait(Executable, {}, {}, Redirects,
+ /* SecondsToWait */ 0,
+ /*MemoryLimit*/ 0, &ErrorMessage))
+ return llvm::createStringError(std::error_code(),
+ Executable + ": " + ErrorMessage);
+
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> OutputBuf =
+ llvm::MemoryBuffer::getFile(OutputFile.c_str());
+ if (!OutputBuf)
+ return llvm::createStringError(OutputBuf.getError(),
+ "Failed to read stdout of " + Executable +
+ ": " + OutputBuf.getError().message());
+ return std::move(*OutputBuf);
+}
+
void ToolChain::setTripleEnvironment(llvm::Triple::EnvironmentType Env) {
Triple.setEnvironment(Env);
if (EffectiveTriple != llvm::Triple())
@@ -150,9 +178,9 @@ ToolChain::getSanitizerArgs(const llvm::opt::ArgList &JobArgs) const {
}
const XRayArgs& ToolChain::getXRayArgs() const {
- if (!XRayArguments.get())
+ if (!XRayArguments)
XRayArguments.reset(new XRayArgs(*this, Args));
- return *XRayArguments.get();
+ return *XRayArguments;
}
namespace {
@@ -185,11 +213,11 @@ static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {
{"clang-dxc", "--driver-mode=dxc"},
};
- for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i) {
- StringRef Suffix(DriverSuffixes[i].Suffix);
+ for (const auto &DS : DriverSuffixes) {
+ StringRef Suffix(DS.Suffix);
if (ProgName.endswith(Suffix)) {
Pos = ProgName.size() - Suffix.size();
- return &DriverSuffixes[i];
+ return &DS;
}
}
return nullptr;
@@ -198,7 +226,7 @@ static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {
/// Normalize the program name from argv[0] by stripping the file extension if
/// present and lower-casing the string on Windows.
static std::string normalizeProgramName(llvm::StringRef Argv0) {
- std::string ProgName = std::string(llvm::sys::path::stem(Argv0));
+ std::string ProgName = std::string(llvm::sys::path::filename(Argv0));
if (is_style_windows(llvm::sys::path::Style::native)) {
// Transform to lowercase for case insensitive file systems.
std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(),
@@ -217,6 +245,13 @@ static const DriverSuffix *parseDriverSuffix(StringRef ProgName, size_t &Pos) {
// added via -target as implicit first argument.
const DriverSuffix *DS = FindDriverSuffix(ProgName, Pos);
+ if (!DS && ProgName.endswith(".exe")) {
+ // Try again after stripping the executable suffix:
+ // clang++.exe -> clang++
+ ProgName = ProgName.drop_back(StringRef(".exe").size());
+ DS = FindDriverSuffix(ProgName, Pos);
+ }
+
if (!DS) {
// Try again after stripping any trailing version number:
// clang++3.5 -> clang++
@@ -287,8 +322,9 @@ std::string ToolChain::getInputFilename(const InputInfo &Input) const {
return Input.getFilename();
}
-bool ToolChain::IsUnwindTablesDefault(const ArgList &Args) const {
- return false;
+ToolChain::UnwindTableLevel
+ToolChain::getDefaultUnwindTableLevel(const ArgList &Args) const {
+ return UnwindTableLevel::None;
}
Tool *ToolChain::getClang() const {
@@ -351,12 +387,6 @@ Tool *ToolChain::getOffloadBundler() const {
return OffloadBundler.get();
}
-Tool *ToolChain::getOffloadWrapper() const {
- if (!OffloadWrapper)
- OffloadWrapper.reset(new tools::OffloadWrapper(*this));
- return OffloadWrapper.get();
-}
-
Tool *ToolChain::getOffloadPackager() const {
if (!OffloadPackager)
OffloadPackager.reset(new tools::OffloadPackager(*this));
@@ -393,7 +423,6 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const {
case Action::CompileJobClass:
case Action::PrecompileJobClass:
- case Action::HeaderModulePrecompileJobClass:
case Action::PreprocessJobClass:
case Action::ExtractAPIJobClass:
case Action::AnalyzeJobClass:
@@ -406,8 +435,6 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const {
case Action::OffloadUnbundlingJobClass:
return getOffloadBundler();
- case Action::OffloadWrapperJobClass:
- return getOffloadWrapper();
case Action::OffloadPackagerJobClass:
return getOffloadPackager();
case Action::LinkerWrapperJobClass:
@@ -422,6 +449,9 @@ static StringRef getArchNameForCompilerRTLib(const ToolChain &TC,
const llvm::Triple &Triple = TC.getTriple();
bool IsWindows = Triple.isOSWindows();
+ if (TC.isBareMetal())
+ return Triple.getArchName();
+
if (TC.getArch() == llvm::Triple::arm || TC.getArch() == llvm::Triple::armeb)
return (arm::getARMFloatABI(TC, Args) == arm::FloatABI::Hard && !IsWindows)
? "armhf"
@@ -459,7 +489,10 @@ StringRef ToolChain::getOSLibName() const {
std::string ToolChain::getCompilerRTPath() const {
SmallString<128> Path(getDriver().ResourceDir);
- if (Triple.isOSUnknown()) {
+ if (isBareMetal()) {
+ llvm::sys::path::append(Path, "lib", getOSLibName());
+ Path += SelectedMultilib.gccSuffix();
+ } else if (Triple.isOSUnknown()) {
llvm::sys::path::append(Path, "lib");
} else {
llvm::sys::path::append(Path, "lib", getOSLibName());
@@ -622,13 +655,18 @@ std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD) const {
// --ld-path= takes precedence over -fuse-ld= and specifies the executable
// name. -B, COMPILER_PATH and PATH and consulted if the value does not
// contain a path component separator.
+ // -fuse-ld=lld can be used with --ld-path= to inform clang that the binary
+ // that --ld-path= points to is lld.
if (const Arg *A = Args.getLastArg(options::OPT_ld_path_EQ)) {
std::string Path(A->getValue());
if (!Path.empty()) {
if (llvm::sys::path::parent_path(Path).empty())
Path = GetProgramPath(A->getValue());
- if (llvm::sys::fs::can_execute(Path))
+ if (llvm::sys::fs::can_execute(Path)) {
+ if (LinkerIsLLD)
+ *LinkerIsLLD = UseLinker == "lld";
return std::string(Path);
+ }
}
getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args);
return GetProgramPath(getDefaultLinker());
@@ -805,6 +843,9 @@ void ToolChain::addClangTargetOptions(
const ArgList &DriverArgs, ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadKind) const {}
+void ToolChain::addClangCC1ASTargetOptions(const ArgList &Args,
+ ArgStringList &CC1ASArgs) const {}
+
void ToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {}
void ToolChain::addProfileRTLibs(const llvm::opt::ArgList &Args,
@@ -991,8 +1032,15 @@ void ToolChain::AddClangCXXStdlibIsystemArgs(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
DriverArgs.ClaimAllArgs(options::OPT_stdlibxx_isystem);
- if (!DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdincxx,
- options::OPT_nostdlibinc))
+ // This intentionally only looks at -nostdinc++, and not -nostdinc or
+ // -nostdlibinc. The purpose of -stdlib++-isystem is to support toolchain
+ // setups with non-standard search logic for the C++ headers, while still
+ // allowing users of the toolchain to bring their own C++ headers. Such a
+ // toolchain likely also has non-standard search logic for the C headers and
+ // uses -nostdinc to suppress the default logic, but -stdlib++-isystem should
+ // still work in that case and only be suppressed by an explicit -nostdinc++
+ // in a project using the toolchain.
+ if (!DriverArgs.hasArg(options::OPT_nostdincxx))
for (const auto &P :
DriverArgs.getAllArgValues(options::OPT_stdlibxx_isystem))
addSystemInclude(DriverArgs, CC1Args, P);
@@ -1066,6 +1114,11 @@ bool ToolChain::addFastMathRuntimeIfAvailable(const ArgList &Args,
return false;
}
+Expected<SmallVector<std::string>>
+ToolChain::getSystemGPUArchs(const llvm::opt::ArgList &Args) const {
+ return SmallVector<std::string>();
+}
+
SanitizerMask ToolChain::getSupportedSanitizers() const {
// Return sanitizers which don't require runtime support and are not
// platform dependent.
@@ -1075,7 +1128,7 @@ SanitizerMask ToolChain::getSupportedSanitizers() const {
~SanitizerKind::Function) |
(SanitizerKind::CFI & ~SanitizerKind::CFIICall) |
SanitizerKind::CFICastStrict | SanitizerKind::FloatDivideByZero |
- SanitizerKind::UnsignedIntegerOverflow |
+ SanitizerKind::KCFI | SanitizerKind::UnsignedIntegerOverflow |
SanitizerKind::UnsignedShiftBase | SanitizerKind::ImplicitConversion |
SanitizerKind::Nullability | SanitizerKind::LocalBounds;
if (getTriple().getArch() == llvm::Triple::x86 ||
@@ -1098,7 +1151,7 @@ void ToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {}
llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
-ToolChain::getHIPDeviceLibs(const ArgList &DriverArgs) const {
+ToolChain::getDeviceLibs(const ArgList &DriverArgs) const {
return {};
}
@@ -1280,17 +1333,17 @@ llvm::opt::DerivedArgList *ToolChain::TranslateXarchArgs(
DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
bool Modified = false;
- bool IsGPU = OFK == Action::OFK_Cuda || OFK == Action::OFK_HIP;
+ bool IsDevice = OFK != Action::OFK_None && OFK != Action::OFK_Host;
for (Arg *A : Args) {
bool NeedTrans = false;
bool Skip = false;
if (A->getOption().matches(options::OPT_Xarch_device)) {
- NeedTrans = IsGPU;
- Skip = !IsGPU;
+ NeedTrans = IsDevice;
+ Skip = !IsDevice;
} else if (A->getOption().matches(options::OPT_Xarch_host)) {
- NeedTrans = !IsGPU;
- Skip = IsGPU;
- } else if (A->getOption().matches(options::OPT_Xarch__) && IsGPU) {
+ NeedTrans = !IsDevice;
+ Skip = IsDevice;
+ } else if (A->getOption().matches(options::OPT_Xarch__) && IsDevice) {
// Do not translate -Xarch_ options for non CUDA/HIP toolchain since
// they may need special translation.
// Skip this argument unless the architecture matches BoundArch