aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Driver/ToolChains/CommonArgs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Driver/ToolChains/CommonArgs.cpp')
-rw-r--r--lib/Driver/ToolChains/CommonArgs.cpp356
1 files changed, 180 insertions, 176 deletions
diff --git a/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp
index 99691cb43dc4..10743559e048 100644
--- a/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/lib/Driver/ToolChains/CommonArgs.cpp
@@ -11,8 +11,12 @@
#include "Arch/ARM.h"
#include "Arch/Mips.h"
#include "Arch/PPC.h"
+#include "Arch/RISCV.h"
+#include "Arch/Sparc.h"
#include "Arch/SystemZ.h"
#include "Arch/X86.h"
+#include "AMDGPU.h"
+#include "MSP430.h"
#include "HIP.h"
#include "Hexagon.h"
#include "InputInfo.h"
@@ -145,6 +149,11 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs,
// (constructed via -Xarch_).
Args.AddAllArgValues(CmdArgs, options::OPT_Zlinker_input);
+ // LIBRARY_PATH are included before user inputs and only supported on native
+ // toolchains.
+ if (!TC.isCrossCompiling())
+ addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH");
+
for (const auto &II : Inputs) {
// If the current tool chain refers to an OpenMP or HIP offloading host, we
// should ignore inputs that refer to OpenMP or HIP offloading devices -
@@ -182,12 +191,6 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs,
A.renderAsInput(Args, CmdArgs);
}
}
-
- // LIBRARY_PATH - included following the user specified library paths.
- // and only supported on native toolchains.
- if (!TC.isCrossCompiling()) {
- addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH");
- }
}
void tools::AddTargetFeature(const ArgList &Args,
@@ -485,6 +488,14 @@ void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
if (!StatsFile.empty())
CmdArgs.push_back(
Args.MakeArgString(Twine("-plugin-opt=stats-file=") + StatsFile));
+
+ getTargetFeatures(ToolChain, ToolChain.getTriple(), Args, CmdArgs,
+ /* ForAS= */ false, /* ForLTOPlugin= */ true);
+
+ StringRef ABIName = tools::getTargetABI(Args, ToolChain.getTriple());
+ if (!ABIName.empty())
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-plugin-opt=-target-abi=") + ABIName));
}
void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args,
@@ -501,30 +512,41 @@ void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args,
}
bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
- const ArgList &Args, bool IsOffloadingHost,
- bool GompNeedsRT) {
+ const ArgList &Args, bool ForceStaticHostRuntime,
+ bool IsOffloadingHost, bool GompNeedsRT) {
if (!Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
options::OPT_fno_openmp, false))
return false;
- switch (TC.getDriver().getOpenMPRuntime(Args)) {
+ Driver::OpenMPRuntimeKind RTKind = TC.getDriver().getOpenMPRuntime(Args);
+
+ if (RTKind == Driver::OMPRT_Unknown)
+ // Already diagnosed.
+ return false;
+
+ if (ForceStaticHostRuntime)
+ CmdArgs.push_back("-Bstatic");
+
+ switch (RTKind) {
case Driver::OMPRT_OMP:
CmdArgs.push_back("-lomp");
break;
case Driver::OMPRT_GOMP:
CmdArgs.push_back("-lgomp");
-
- if (GompNeedsRT)
- CmdArgs.push_back("-lrt");
break;
case Driver::OMPRT_IOMP5:
CmdArgs.push_back("-liomp5");
break;
case Driver::OMPRT_Unknown:
- // Already diagnosed.
- return false;
+ break;
}
+ if (ForceStaticHostRuntime)
+ CmdArgs.push_back("-Bdynamic");
+
+ if (RTKind == Driver::OMPRT_GOMP && GompNeedsRT)
+ CmdArgs.push_back("-lrt");
+
if (IsOffloadingHost)
CmdArgs.push_back("-lomptarget");
@@ -605,29 +627,29 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
// Collect shared runtimes.
if (SanArgs.needsSharedRt()) {
- if (SanArgs.needsAsanRt()) {
+ if (SanArgs.needsAsanRt() && SanArgs.linkRuntimes()) {
SharedRuntimes.push_back("asan");
if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid())
HelperStaticRuntimes.push_back("asan-preinit");
}
- if (SanArgs.needsUbsanRt()) {
+ if (SanArgs.needsUbsanRt() && SanArgs.linkRuntimes()) {
if (SanArgs.requiresMinimalRuntime())
SharedRuntimes.push_back("ubsan_minimal");
else
SharedRuntimes.push_back("ubsan_standalone");
}
- if (SanArgs.needsScudoRt()) {
+ if (SanArgs.needsScudoRt() && SanArgs.linkRuntimes()) {
if (SanArgs.requiresMinimalRuntime())
SharedRuntimes.push_back("scudo_minimal");
else
SharedRuntimes.push_back("scudo");
}
- if (SanArgs.needsHwasanRt())
+ if (SanArgs.needsHwasanRt() && SanArgs.linkRuntimes())
SharedRuntimes.push_back("hwasan");
}
// The stats_client library is also statically linked into DSOs.
- if (SanArgs.needsStatsRt())
+ if (SanArgs.needsStatsRt() && SanArgs.linkRuntimes())
StaticRuntimes.push_back("stats_client");
// Collect static runtimes.
@@ -635,32 +657,32 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
// Don't link static runtimes into DSOs or if -shared-libasan.
return;
}
- if (SanArgs.needsAsanRt()) {
+ if (SanArgs.needsAsanRt() && SanArgs.linkRuntimes()) {
StaticRuntimes.push_back("asan");
if (SanArgs.linkCXXRuntimes())
StaticRuntimes.push_back("asan_cxx");
}
- if (SanArgs.needsHwasanRt()) {
+ if (SanArgs.needsHwasanRt() && SanArgs.linkRuntimes()) {
StaticRuntimes.push_back("hwasan");
if (SanArgs.linkCXXRuntimes())
StaticRuntimes.push_back("hwasan_cxx");
}
- if (SanArgs.needsDfsanRt())
+ if (SanArgs.needsDfsanRt() && SanArgs.linkRuntimes())
StaticRuntimes.push_back("dfsan");
- if (SanArgs.needsLsanRt())
+ if (SanArgs.needsLsanRt() && SanArgs.linkRuntimes())
StaticRuntimes.push_back("lsan");
- if (SanArgs.needsMsanRt()) {
+ if (SanArgs.needsMsanRt() && SanArgs.linkRuntimes()) {
StaticRuntimes.push_back("msan");
if (SanArgs.linkCXXRuntimes())
StaticRuntimes.push_back("msan_cxx");
}
- if (SanArgs.needsTsanRt()) {
+ if (SanArgs.needsTsanRt() && SanArgs.linkRuntimes()) {
StaticRuntimes.push_back("tsan");
if (SanArgs.linkCXXRuntimes())
StaticRuntimes.push_back("tsan_cxx");
}
- if (SanArgs.needsUbsanRt()) {
+ if (SanArgs.needsUbsanRt() && SanArgs.linkRuntimes()) {
if (SanArgs.requiresMinimalRuntime()) {
StaticRuntimes.push_back("ubsan_minimal");
} else {
@@ -669,22 +691,22 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
StaticRuntimes.push_back("ubsan_standalone_cxx");
}
}
- if (SanArgs.needsSafeStackRt()) {
+ if (SanArgs.needsSafeStackRt() && SanArgs.linkRuntimes()) {
NonWholeStaticRuntimes.push_back("safestack");
RequiredSymbols.push_back("__safestack_init");
}
- if (SanArgs.needsCfiRt())
+ if (SanArgs.needsCfiRt() && SanArgs.linkRuntimes())
StaticRuntimes.push_back("cfi");
- if (SanArgs.needsCfiDiagRt()) {
+ if (SanArgs.needsCfiDiagRt() && SanArgs.linkRuntimes()) {
StaticRuntimes.push_back("cfi_diag");
if (SanArgs.linkCXXRuntimes())
StaticRuntimes.push_back("ubsan_standalone_cxx");
}
- if (SanArgs.needsStatsRt()) {
+ if (SanArgs.needsStatsRt() && SanArgs.linkRuntimes()) {
NonWholeStaticRuntimes.push_back("stats");
RequiredSymbols.push_back("__sanitizer_stats_register");
}
- if (SanArgs.needsScudoRt()) {
+ if (SanArgs.needsScudoRt() && SanArgs.linkRuntimes()) {
if (SanArgs.requiresMinimalRuntime()) {
StaticRuntimes.push_back("scudo_minimal");
if (SanArgs.linkCXXRuntimes())
@@ -707,9 +729,10 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
NonWholeStaticRuntimes, HelperStaticRuntimes,
RequiredSymbols);
+ const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
// Inject libfuzzer dependencies.
- if (TC.getSanitizerArgs().needsFuzzer()
- && !Args.hasArg(options::OPT_shared)) {
+ if (SanArgs.needsFuzzer() && SanArgs.linkRuntimes() &&
+ !Args.hasArg(options::OPT_shared)) {
addSanitizerRuntime(TC, Args, CmdArgs, "fuzzer", false, true);
if (!Args.hasArg(clang::driver::options::OPT_nostdlibxx))
@@ -738,7 +761,6 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
if (AddExportDynamic)
CmdArgs.push_back("--export-dynamic");
- const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
if (SanArgs.hasCrossDsoCfi() && !AddExportDynamic)
CmdArgs.push_back("-export-dynamic-symbol=__cfi_check");
@@ -823,10 +845,10 @@ void tools::SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T,
InputInfo II(types::TY_Object, Output.getFilename(), Output.getFilename());
// First extract the dwo sections.
- C.addCommand(llvm::make_unique<Command>(JA, T, Exec, ExtractArgs, II));
+ C.addCommand(std::make_unique<Command>(JA, T, Exec, ExtractArgs, II));
// Then remove them from the original .o file.
- C.addCommand(llvm::make_unique<Command>(JA, T, Exec, StripArgs, II));
+ C.addCommand(std::make_unique<Command>(JA, T, Exec, StripArgs, II));
}
// Claim options we don't want to warn if they are unused. We do this for
@@ -1176,7 +1198,6 @@ static void AddUnwindLibrary(const ToolChain &TC, const Driver &D,
case ToolChain::UNW_None:
return;
case ToolChain::UNW_Libgcc: {
- LibGccType LGT = getLibGccType(D, Args);
if (LGT == LibGccType::StaticLibGcc)
CmdArgs.push_back("-lgcc_eh");
else
@@ -1235,131 +1256,6 @@ void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D,
}
}
-/// Add OpenMP linker script arguments at the end of the argument list so that
-/// the fat binary is built by embedding each of the device images into the
-/// host. The linker script also defines a few symbols required by the code
-/// generation so that the images can be easily retrieved at runtime by the
-/// offloading library. This should be used only in tool chains that support
-/// linker scripts.
-void tools::AddOpenMPLinkerScript(const ToolChain &TC, Compilation &C,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args, ArgStringList &CmdArgs,
- const JobAction &JA) {
-
- // If this is not an OpenMP host toolchain, we don't need to do anything.
- if (!JA.isHostOffloading(Action::OFK_OpenMP))
- return;
-
- // Create temporary linker script. Keep it if save-temps is enabled.
- const char *LKS;
- SmallString<256> Name = llvm::sys::path::filename(Output.getFilename());
- if (C.getDriver().isSaveTempsEnabled()) {
- llvm::sys::path::replace_extension(Name, "lk");
- LKS = C.getArgs().MakeArgString(Name.c_str());
- } else {
- llvm::sys::path::replace_extension(Name, "");
- Name = C.getDriver().GetTemporaryPath(Name, "lk");
- LKS = C.addTempFile(C.getArgs().MakeArgString(Name.c_str()));
- }
-
- // Add linker script option to the command.
- CmdArgs.push_back("-T");
- CmdArgs.push_back(LKS);
-
- // Create a buffer to write the contents of the linker script.
- std::string LksBuffer;
- llvm::raw_string_ostream LksStream(LksBuffer);
-
- // Get the OpenMP offload tool chains so that we can extract the triple
- // associated with each device input.
- auto OpenMPToolChains = C.getOffloadToolChains<Action::OFK_OpenMP>();
- assert(OpenMPToolChains.first != OpenMPToolChains.second &&
- "No OpenMP toolchains??");
-
- // Track the input file name and device triple in order to build the script,
- // inserting binaries in the designated sections.
- SmallVector<std::pair<std::string, const char *>, 8> InputBinaryInfo;
-
- // Add commands to embed target binaries. We ensure that each section and
- // image is 16-byte aligned. This is not mandatory, but increases the
- // likelihood of data to be aligned with a cache block in several main host
- // machines.
- LksStream << "/*\n";
- LksStream << " OpenMP Offload Linker Script\n";
- LksStream << " *** Automatically generated by Clang ***\n";
- LksStream << "*/\n";
- LksStream << "TARGET(binary)\n";
- auto DTC = OpenMPToolChains.first;
- for (auto &II : Inputs) {
- const Action *A = II.getAction();
- // Is this a device linking action?
- if (A && isa<LinkJobAction>(A) &&
- A->isDeviceOffloading(Action::OFK_OpenMP)) {
- assert(DTC != OpenMPToolChains.second &&
- "More device inputs than device toolchains??");
- InputBinaryInfo.push_back(std::make_pair(
- DTC->second->getTriple().normalize(), II.getFilename()));
- ++DTC;
- LksStream << "INPUT(" << II.getFilename() << ")\n";
- }
- }
-
- assert(DTC == OpenMPToolChains.second &&
- "Less device inputs than device toolchains??");
-
- LksStream << "SECTIONS\n";
- LksStream << "{\n";
-
- // Put each target binary into a separate section.
- for (const auto &BI : InputBinaryInfo) {
- LksStream << " .omp_offloading." << BI.first << " :\n";
- LksStream << " ALIGN(0x10)\n";
- LksStream << " {\n";
- LksStream << " PROVIDE_HIDDEN(.omp_offloading.img_start." << BI.first
- << " = .);\n";
- LksStream << " " << BI.second << "\n";
- LksStream << " PROVIDE_HIDDEN(.omp_offloading.img_end." << BI.first
- << " = .);\n";
- LksStream << " }\n";
- }
-
- // Add commands to define host entries begin and end. We use 1-byte subalign
- // so that the linker does not add any padding and the elements in this
- // section form an array.
- LksStream << " .omp_offloading.entries :\n";
- LksStream << " ALIGN(0x10)\n";
- LksStream << " SUBALIGN(0x01)\n";
- LksStream << " {\n";
- LksStream << " PROVIDE_HIDDEN(.omp_offloading.entries_begin = .);\n";
- LksStream << " *(.omp_offloading.entries)\n";
- LksStream << " PROVIDE_HIDDEN(.omp_offloading.entries_end = .);\n";
- LksStream << " }\n";
- LksStream << "}\n";
- LksStream << "INSERT BEFORE .data\n";
- LksStream.flush();
-
- // Dump the contents of the linker script if the user requested that. We
- // support this option to enable testing of behavior with -###.
- if (C.getArgs().hasArg(options::OPT_fopenmp_dump_offload_linker_script))
- llvm::errs() << LksBuffer;
-
- // If this is a dry run, do not create the linker script file.
- if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH))
- return;
-
- // Open script file and write the contents.
- std::error_code EC;
- llvm::raw_fd_ostream Lksf(LKS, EC, llvm::sys::fs::F_None);
-
- if (EC) {
- C.getDriver().Diag(clang::diag::err_unable_to_make_temp) << EC.message();
- return;
- }
-
- Lksf << LksBuffer;
-}
-
/// Add HIP linker script arguments at the end of the argument list so that
/// the fat binary is built by embedding the device images into the host. The
/// linker script also defines a symbol required by the code generation so that
@@ -1389,14 +1285,12 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C,
// Create temporary linker script. Keep it if save-temps is enabled.
const char *LKS;
- SmallString<256> Name = llvm::sys::path::filename(Output.getFilename());
+ std::string Name = llvm::sys::path::filename(Output.getFilename());
if (C.getDriver().isSaveTempsEnabled()) {
- llvm::sys::path::replace_extension(Name, "lk");
- LKS = C.getArgs().MakeArgString(Name.c_str());
+ LKS = C.getArgs().MakeArgString(Name + ".lk");
} else {
- llvm::sys::path::replace_extension(Name, "");
- Name = C.getDriver().GetTemporaryPath(Name, "lk");
- LKS = C.addTempFile(C.getArgs().MakeArgString(Name.c_str()));
+ auto TmpName = C.getDriver().GetTemporaryPath(Name, "lk");
+ LKS = C.addTempFile(C.getArgs().MakeArgString(TmpName));
}
// Add linker script option to the command.
@@ -1414,11 +1308,13 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C,
"Wrong platform");
(void)HIPTC;
- // 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()));
+ const char *BundleFile;
+ if (C.getDriver().isSaveTempsEnabled()) {
+ BundleFile = C.getArgs().MakeArgString(Name + ".hipfb");
+ } else {
+ auto TmpName = C.getDriver().GetTemporaryPath(Name, "hipfb");
+ BundleFile = C.addTempFile(C.getArgs().MakeArgString(TmpName));
+ }
AMDGCN::constructHIPFatbinCommand(C, JA, BundleFile, DeviceInputs, Args, T);
// Add commands to embed target binaries. We ensure that each section and
@@ -1430,14 +1326,14 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C,
LksStream << " *** Automatically generated by Clang ***\n";
LksStream << "*/\n";
LksStream << "TARGET(binary)\n";
- LksStream << "INPUT(" << BundleFileName << ")\n";
+ LksStream << "INPUT(" << BundleFile << ")\n";
LksStream << "SECTIONS\n";
LksStream << "{\n";
LksStream << " .hip_fatbin :\n";
LksStream << " ALIGN(0x10)\n";
LksStream << " {\n";
LksStream << " PROVIDE_HIDDEN(__hip_fatbin = .);\n";
- LksStream << " " << BundleFileName << "\n";
+ LksStream << " " << BundleFile << "\n";
LksStream << " }\n";
LksStream << " /DISCARD/ :\n";
LksStream << " {\n";
@@ -1458,7 +1354,7 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C,
// Open script file and write the contents.
std::error_code EC;
- llvm::raw_fd_ostream Lksf(LKS, EC, llvm::sys::fs::F_None);
+ llvm::raw_fd_ostream Lksf(LKS, EC, llvm::sys::fs::OF_None);
if (EC) {
C.getDriver().Diag(clang::diag::err_unable_to_make_temp) << EC.message();
@@ -1496,3 +1392,111 @@ void tools::addMultilibFlag(bool Enabled, const char *const Flag,
Multilib::flags_list &Flags) {
Flags.push_back(std::string(Enabled ? "+" : "-") + Flag);
}
+
+static void getWebAssemblyTargetFeatures(const ArgList &Args,
+ std::vector<StringRef> &Features) {
+ handleTargetFeaturesGroup(Args, Features, options::OPT_m_wasm_Features_Group);
+}
+
+void tools::getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
+ const ArgList &Args, ArgStringList &CmdArgs, bool ForAS,
+ bool ForLTOPlugin) {
+
+ const Driver &D = TC.getDriver();
+ std::vector<StringRef> Features;
+ switch (Triple.getArch()) {
+ default:
+ break;
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ mips::getMIPSTargetFeatures(D, Triple, Args, Features);
+ break;
+
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ arm::getARMTargetFeatures(TC, Triple, Args, CmdArgs, Features, ForAS);
+ break;
+
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::ppc64le:
+ ppc::getPPCTargetFeatures(D, Triple, Args, Features);
+ break;
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ riscv::getRISCVTargetFeatures(D, Triple, Args, Features);
+ break;
+ case llvm::Triple::systemz:
+ systemz::getSystemZTargetFeatures(Args, Features);
+ break;
+ case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_be:
+ aarch64::getAArch64TargetFeatures(D, Triple, Args, Features);
+ break;
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ x86::getX86TargetFeatures(D, Triple, Args, Features);
+ break;
+ case llvm::Triple::hexagon:
+ hexagon::getHexagonTargetFeatures(D, Args, Features);
+ break;
+ case llvm::Triple::wasm32:
+ case llvm::Triple::wasm64:
+ getWebAssemblyTargetFeatures(Args, Features);
+ break;
+ case llvm::Triple::sparc:
+ case llvm::Triple::sparcel:
+ case llvm::Triple::sparcv9:
+ sparc::getSparcTargetFeatures(D, Args, Features);
+ break;
+ case llvm::Triple::r600:
+ case llvm::Triple::amdgcn:
+ amdgpu::getAMDGPUTargetFeatures(D, Args, Features);
+ break;
+ case llvm::Triple::msp430:
+ msp430::getMSP430TargetFeatures(D, Args, Features);
+ }
+
+ // Find the last of each feature.
+ llvm::StringMap<unsigned> LastOpt;
+ for (unsigned I = 0, N = Features.size(); I < N; ++I) {
+ StringRef Name = Features[I];
+ assert(Name[0] == '-' || Name[0] == '+');
+ LastOpt[Name.drop_front(1)] = I;
+ }
+
+ for (unsigned I = 0, N = Features.size(); I < N; ++I) {
+ // If this feature was overridden, ignore it.
+ StringRef Name = Features[I];
+ llvm::StringMap<unsigned>::iterator LastI =
+ LastOpt.find(Name.drop_front(1));
+ assert(LastI != LastOpt.end());
+ unsigned Last = LastI->second;
+ if (Last != I)
+ continue;
+ if (!ForLTOPlugin) {
+ CmdArgs.push_back("-target-feature");
+ CmdArgs.push_back(Name.data());
+ } else {
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-plugin-opt=-mattr=") + Name));
+ }
+ }
+}
+
+StringRef tools::getTargetABI(const ArgList &Args, const llvm::Triple &Triple) {
+ // TODO: Support the other target ABI
+ switch (Triple.getArch()) {
+ default:
+ break;
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ return tools::riscv::getRISCVABI(Args, Triple);
+ break;
+ }
+ return StringRef();
+}