xref: /openbsd-src/gnu/llvm/clang/lib/Basic/Targets/RISCV.cpp (revision 7a9b00ce7716f522d49aa36666c74a71cd12203a)
1e5dd7070Spatrick //===--- RISCV.cpp - Implement RISCV target feature support ---------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // This file implements RISCV TargetInfo objects.
10e5dd7070Spatrick //
11e5dd7070Spatrick //===----------------------------------------------------------------------===//
12e5dd7070Spatrick 
13e5dd7070Spatrick #include "RISCV.h"
14*7a9b00ceSrobert #include "clang/Basic/Diagnostic.h"
15e5dd7070Spatrick #include "clang/Basic/MacroBuilder.h"
16a0747c9fSpatrick #include "clang/Basic/TargetBuiltins.h"
17e5dd7070Spatrick #include "llvm/ADT/StringSwitch.h"
18*7a9b00ceSrobert #include "llvm/Support/raw_ostream.h"
19*7a9b00ceSrobert #include "llvm/TargetParser/RISCVTargetParser.h"
20*7a9b00ceSrobert #include <optional>
21e5dd7070Spatrick 
22e5dd7070Spatrick using namespace clang;
23e5dd7070Spatrick using namespace clang::targets;
24e5dd7070Spatrick 
getGCCRegNames() const25e5dd7070Spatrick ArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const {
26e5dd7070Spatrick   static const char *const GCCRegNames[] = {
27e5dd7070Spatrick       // Integer registers
28e5dd7070Spatrick       "x0",  "x1",  "x2",  "x3",  "x4",  "x5",  "x6",  "x7",
29e5dd7070Spatrick       "x8",  "x9",  "x10", "x11", "x12", "x13", "x14", "x15",
30e5dd7070Spatrick       "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
31e5dd7070Spatrick       "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31",
32e5dd7070Spatrick 
33e5dd7070Spatrick       // Floating point registers
34e5dd7070Spatrick       "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
35e5dd7070Spatrick       "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",
36e5dd7070Spatrick       "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
37a0747c9fSpatrick       "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
38a0747c9fSpatrick 
39a0747c9fSpatrick       // Vector registers
40a0747c9fSpatrick       "v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6",  "v7",
41a0747c9fSpatrick       "v8",  "v9",  "v10", "v11", "v12", "v13", "v14", "v15",
42a0747c9fSpatrick       "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
43a0747c9fSpatrick       "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"};
44*7a9b00ceSrobert   return llvm::ArrayRef(GCCRegNames);
45e5dd7070Spatrick }
46e5dd7070Spatrick 
getGCCRegAliases() const47e5dd7070Spatrick ArrayRef<TargetInfo::GCCRegAlias> RISCVTargetInfo::getGCCRegAliases() const {
48e5dd7070Spatrick   static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
49e5dd7070Spatrick       {{"zero"}, "x0"}, {{"ra"}, "x1"},   {{"sp"}, "x2"},    {{"gp"}, "x3"},
50e5dd7070Spatrick       {{"tp"}, "x4"},   {{"t0"}, "x5"},   {{"t1"}, "x6"},    {{"t2"}, "x7"},
51e5dd7070Spatrick       {{"s0"}, "x8"},   {{"s1"}, "x9"},   {{"a0"}, "x10"},   {{"a1"}, "x11"},
52e5dd7070Spatrick       {{"a2"}, "x12"},  {{"a3"}, "x13"},  {{"a4"}, "x14"},   {{"a5"}, "x15"},
53e5dd7070Spatrick       {{"a6"}, "x16"},  {{"a7"}, "x17"},  {{"s2"}, "x18"},   {{"s3"}, "x19"},
54e5dd7070Spatrick       {{"s4"}, "x20"},  {{"s5"}, "x21"},  {{"s6"}, "x22"},   {{"s7"}, "x23"},
55e5dd7070Spatrick       {{"s8"}, "x24"},  {{"s9"}, "x25"},  {{"s10"}, "x26"},  {{"s11"}, "x27"},
56e5dd7070Spatrick       {{"t3"}, "x28"},  {{"t4"}, "x29"},  {{"t5"}, "x30"},   {{"t6"}, "x31"},
57e5dd7070Spatrick       {{"ft0"}, "f0"},  {{"ft1"}, "f1"},  {{"ft2"}, "f2"},   {{"ft3"}, "f3"},
58e5dd7070Spatrick       {{"ft4"}, "f4"},  {{"ft5"}, "f5"},  {{"ft6"}, "f6"},   {{"ft7"}, "f7"},
59e5dd7070Spatrick       {{"fs0"}, "f8"},  {{"fs1"}, "f9"},  {{"fa0"}, "f10"},  {{"fa1"}, "f11"},
60e5dd7070Spatrick       {{"fa2"}, "f12"}, {{"fa3"}, "f13"}, {{"fa4"}, "f14"},  {{"fa5"}, "f15"},
61e5dd7070Spatrick       {{"fa6"}, "f16"}, {{"fa7"}, "f17"}, {{"fs2"}, "f18"},  {{"fs3"}, "f19"},
62e5dd7070Spatrick       {{"fs4"}, "f20"}, {{"fs5"}, "f21"}, {{"fs6"}, "f22"},  {{"fs7"}, "f23"},
63e5dd7070Spatrick       {{"fs8"}, "f24"}, {{"fs9"}, "f25"}, {{"fs10"}, "f26"}, {{"fs11"}, "f27"},
64e5dd7070Spatrick       {{"ft8"}, "f28"}, {{"ft9"}, "f29"}, {{"ft10"}, "f30"}, {{"ft11"}, "f31"}};
65*7a9b00ceSrobert   return llvm::ArrayRef(GCCRegAliases);
66e5dd7070Spatrick }
67e5dd7070Spatrick 
validateAsmConstraint(const char * & Name,TargetInfo::ConstraintInfo & Info) const68e5dd7070Spatrick bool RISCVTargetInfo::validateAsmConstraint(
69e5dd7070Spatrick     const char *&Name, TargetInfo::ConstraintInfo &Info) const {
70e5dd7070Spatrick   switch (*Name) {
71e5dd7070Spatrick   default:
72e5dd7070Spatrick     return false;
73e5dd7070Spatrick   case 'I':
74e5dd7070Spatrick     // A 12-bit signed immediate.
75e5dd7070Spatrick     Info.setRequiresImmediate(-2048, 2047);
76e5dd7070Spatrick     return true;
77e5dd7070Spatrick   case 'J':
78e5dd7070Spatrick     // Integer zero.
79e5dd7070Spatrick     Info.setRequiresImmediate(0);
80e5dd7070Spatrick     return true;
81e5dd7070Spatrick   case 'K':
82e5dd7070Spatrick     // A 5-bit unsigned immediate for CSR access instructions.
83e5dd7070Spatrick     Info.setRequiresImmediate(0, 31);
84e5dd7070Spatrick     return true;
85e5dd7070Spatrick   case 'f':
86e5dd7070Spatrick     // A floating-point register.
87e5dd7070Spatrick     Info.setAllowsRegister();
88e5dd7070Spatrick     return true;
89e5dd7070Spatrick   case 'A':
90e5dd7070Spatrick     // An address that is held in a general-purpose register.
91e5dd7070Spatrick     Info.setAllowsMemory();
92e5dd7070Spatrick     return true;
93a0747c9fSpatrick   case 'S': // A symbolic address
94a0747c9fSpatrick     Info.setAllowsRegister();
95a0747c9fSpatrick     return true;
96a0747c9fSpatrick   case 'v':
97a0747c9fSpatrick     // A vector register.
98a0747c9fSpatrick     if (Name[1] == 'r' || Name[1] == 'm') {
99a0747c9fSpatrick       Info.setAllowsRegister();
100a0747c9fSpatrick       Name += 1;
101a0747c9fSpatrick       return true;
102e5dd7070Spatrick     }
103a0747c9fSpatrick     return false;
104a0747c9fSpatrick   }
105a0747c9fSpatrick }
106a0747c9fSpatrick 
convertConstraint(const char * & Constraint) const107a0747c9fSpatrick std::string RISCVTargetInfo::convertConstraint(const char *&Constraint) const {
108a0747c9fSpatrick   std::string R;
109a0747c9fSpatrick   switch (*Constraint) {
110a0747c9fSpatrick   case 'v':
111*7a9b00ceSrobert     R = std::string("^") + std::string(Constraint, 2);
112a0747c9fSpatrick     Constraint += 1;
113a0747c9fSpatrick     break;
114a0747c9fSpatrick   default:
115a0747c9fSpatrick     R = TargetInfo::convertConstraint(Constraint);
116a0747c9fSpatrick     break;
117a0747c9fSpatrick   }
118a0747c9fSpatrick   return R;
119e5dd7070Spatrick }
120e5dd7070Spatrick 
getVersionValue(unsigned MajorVersion,unsigned MinorVersion)121*7a9b00ceSrobert static unsigned getVersionValue(unsigned MajorVersion, unsigned MinorVersion) {
122*7a9b00ceSrobert   return MajorVersion * 1000000 + MinorVersion * 1000;
123*7a9b00ceSrobert }
124*7a9b00ceSrobert 
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const125e5dd7070Spatrick void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
126e5dd7070Spatrick                                        MacroBuilder &Builder) const {
127e5dd7070Spatrick   Builder.defineMacro("__ELF__");
128e5dd7070Spatrick   Builder.defineMacro("__riscv");
129e5dd7070Spatrick   bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
130e5dd7070Spatrick   Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32");
131e5dd7070Spatrick   StringRef CodeModel = getTargetOpts().CodeModel;
132*7a9b00ceSrobert   unsigned FLen = ISAInfo->getFLen();
133*7a9b00ceSrobert   unsigned MinVLen = ISAInfo->getMinVLen();
134*7a9b00ceSrobert   unsigned MaxELen = ISAInfo->getMaxELen();
135*7a9b00ceSrobert   unsigned MaxELenFp = ISAInfo->getMaxELenFp();
136e5dd7070Spatrick   if (CodeModel == "default")
137e5dd7070Spatrick     CodeModel = "small";
138e5dd7070Spatrick 
139e5dd7070Spatrick   if (CodeModel == "small")
140e5dd7070Spatrick     Builder.defineMacro("__riscv_cmodel_medlow");
141e5dd7070Spatrick   else if (CodeModel == "medium")
142e5dd7070Spatrick     Builder.defineMacro("__riscv_cmodel_medany");
143e5dd7070Spatrick 
144e5dd7070Spatrick   StringRef ABIName = getABI();
145e5dd7070Spatrick   if (ABIName == "ilp32f" || ABIName == "lp64f")
146e5dd7070Spatrick     Builder.defineMacro("__riscv_float_abi_single");
147e5dd7070Spatrick   else if (ABIName == "ilp32d" || ABIName == "lp64d")
148e5dd7070Spatrick     Builder.defineMacro("__riscv_float_abi_double");
149e5dd7070Spatrick   else
150e5dd7070Spatrick     Builder.defineMacro("__riscv_float_abi_soft");
151e5dd7070Spatrick 
152e5dd7070Spatrick   if (ABIName == "ilp32e")
153e5dd7070Spatrick     Builder.defineMacro("__riscv_abi_rve");
154e5dd7070Spatrick 
155a0747c9fSpatrick   Builder.defineMacro("__riscv_arch_test");
156a0747c9fSpatrick 
157*7a9b00ceSrobert   for (auto &Extension : ISAInfo->getExtensions()) {
158*7a9b00ceSrobert     auto ExtName = Extension.first;
159*7a9b00ceSrobert     auto ExtInfo = Extension.second;
160*7a9b00ceSrobert 
161*7a9b00ceSrobert     Builder.defineMacro(
162*7a9b00ceSrobert         Twine("__riscv_", ExtName),
163*7a9b00ceSrobert         Twine(getVersionValue(ExtInfo.MajorVersion, ExtInfo.MinorVersion)));
164*7a9b00ceSrobert   }
165*7a9b00ceSrobert 
166*7a9b00ceSrobert   if (ISAInfo->hasExtension("m") || ISAInfo->hasExtension("zmmul"))
167e5dd7070Spatrick     Builder.defineMacro("__riscv_mul");
168*7a9b00ceSrobert 
169*7a9b00ceSrobert   if (ISAInfo->hasExtension("m")) {
170e5dd7070Spatrick     Builder.defineMacro("__riscv_div");
171e5dd7070Spatrick     Builder.defineMacro("__riscv_muldiv");
172e5dd7070Spatrick   }
173e5dd7070Spatrick 
174*7a9b00ceSrobert   if (ISAInfo->hasExtension("a")) {
175e5dd7070Spatrick     Builder.defineMacro("__riscv_atomic");
176af2320b8Sderaadt     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
177af2320b8Sderaadt     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
178af2320b8Sderaadt     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
179af2320b8Sderaadt     if (Is64Bit)
180af2320b8Sderaadt       Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
181af2320b8Sderaadt   }
182e5dd7070Spatrick 
183*7a9b00ceSrobert   if (FLen) {
184*7a9b00ceSrobert     Builder.defineMacro("__riscv_flen", Twine(FLen));
185e5dd7070Spatrick     Builder.defineMacro("__riscv_fdiv");
186e5dd7070Spatrick     Builder.defineMacro("__riscv_fsqrt");
187e5dd7070Spatrick   }
188e5dd7070Spatrick 
189*7a9b00ceSrobert   if (MinVLen) {
190*7a9b00ceSrobert     Builder.defineMacro("__riscv_v_min_vlen", Twine(MinVLen));
191*7a9b00ceSrobert     Builder.defineMacro("__riscv_v_elen", Twine(MaxELen));
192*7a9b00ceSrobert     Builder.defineMacro("__riscv_v_elen_fp", Twine(MaxELenFp));
193*7a9b00ceSrobert   }
194ec727ea7Spatrick 
195*7a9b00ceSrobert   if (ISAInfo->hasExtension("c"))
196a0747c9fSpatrick     Builder.defineMacro("__riscv_compressed");
197a0747c9fSpatrick 
198*7a9b00ceSrobert   if (ISAInfo->hasExtension("zve32x")) {
199a0747c9fSpatrick     Builder.defineMacro("__riscv_vector");
200*7a9b00ceSrobert     // Currently we support the v0.11 RISC-V V intrinsics.
201*7a9b00ceSrobert     Builder.defineMacro("__riscv_v_intrinsic", Twine(getVersionValue(0, 11)));
202*7a9b00ceSrobert   }
203a0747c9fSpatrick }
204a0747c9fSpatrick 
205*7a9b00ceSrobert static constexpr Builtin::Info BuiltinInfo[] = {
206a0747c9fSpatrick #define BUILTIN(ID, TYPE, ATTRS)                                               \
207*7a9b00ceSrobert   {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
208a0747c9fSpatrick #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
209*7a9b00ceSrobert   {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
210*7a9b00ceSrobert #include "clang/Basic/BuiltinsRISCVVector.def"
211*7a9b00ceSrobert #define BUILTIN(ID, TYPE, ATTRS)                                               \
212*7a9b00ceSrobert   {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
213*7a9b00ceSrobert #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
214*7a9b00ceSrobert   {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
215a0747c9fSpatrick #include "clang/Basic/BuiltinsRISCV.def"
216a0747c9fSpatrick };
217a0747c9fSpatrick 
getTargetBuiltins() const218a0747c9fSpatrick ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const {
219*7a9b00ceSrobert   return llvm::ArrayRef(BuiltinInfo,
220*7a9b00ceSrobert                         clang::RISCV::LastTSBuiltin - Builtin::FirstTSBuiltin);
221a0747c9fSpatrick }
222a0747c9fSpatrick 
initFeatureMap(llvm::StringMap<bool> & Features,DiagnosticsEngine & Diags,StringRef CPU,const std::vector<std::string> & FeaturesVec) const223a0747c9fSpatrick bool RISCVTargetInfo::initFeatureMap(
224a0747c9fSpatrick     llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
225a0747c9fSpatrick     const std::vector<std::string> &FeaturesVec) const {
226a0747c9fSpatrick 
227*7a9b00ceSrobert   unsigned XLen = 32;
228a0747c9fSpatrick 
229*7a9b00ceSrobert   if (getTriple().getArch() == llvm::Triple::riscv64) {
230*7a9b00ceSrobert     Features["64bit"] = true;
231*7a9b00ceSrobert     XLen = 64;
232*7a9b00ceSrobert   } else {
233*7a9b00ceSrobert     Features["32bit"] = true;
234*7a9b00ceSrobert   }
235*7a9b00ceSrobert 
236*7a9b00ceSrobert   auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, FeaturesVec);
237*7a9b00ceSrobert   if (!ParseResult) {
238*7a9b00ceSrobert     std::string Buffer;
239*7a9b00ceSrobert     llvm::raw_string_ostream OutputErrMsg(Buffer);
240*7a9b00ceSrobert     handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
241*7a9b00ceSrobert       OutputErrMsg << ErrMsg.getMessage();
242*7a9b00ceSrobert     });
243*7a9b00ceSrobert     Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
244*7a9b00ceSrobert     return false;
245*7a9b00ceSrobert   }
246*7a9b00ceSrobert 
247*7a9b00ceSrobert   // RISCVISAInfo makes implications for ISA features
248*7a9b00ceSrobert   std::vector<std::string> ImpliedFeatures = (*ParseResult)->toFeatureVector();
249*7a9b00ceSrobert   // Add non-ISA features like `relax` and `save-restore` back
250*7a9b00ceSrobert   for (const std::string &Feature : FeaturesVec)
251*7a9b00ceSrobert     if (!llvm::is_contained(ImpliedFeatures, Feature))
252*7a9b00ceSrobert       ImpliedFeatures.push_back(Feature);
253*7a9b00ceSrobert 
254*7a9b00ceSrobert   return TargetInfo::initFeatureMap(Features, Diags, CPU, ImpliedFeatures);
255*7a9b00ceSrobert }
256*7a9b00ceSrobert 
257*7a9b00ceSrobert std::optional<std::pair<unsigned, unsigned>>
getVScaleRange(const LangOptions & LangOpts) const258*7a9b00ceSrobert RISCVTargetInfo::getVScaleRange(const LangOptions &LangOpts) const {
259*7a9b00ceSrobert   // RISCV::RVVBitsPerBlock is 64.
260*7a9b00ceSrobert   unsigned VScaleMin = ISAInfo->getMinVLen() / llvm::RISCV::RVVBitsPerBlock;
261*7a9b00ceSrobert 
262*7a9b00ceSrobert   if (LangOpts.VScaleMin || LangOpts.VScaleMax) {
263*7a9b00ceSrobert     // Treat Zvl*b as a lower bound on vscale.
264*7a9b00ceSrobert     VScaleMin = std::max(VScaleMin, LangOpts.VScaleMin);
265*7a9b00ceSrobert     unsigned VScaleMax = LangOpts.VScaleMax;
266*7a9b00ceSrobert     if (VScaleMax != 0 && VScaleMax < VScaleMin)
267*7a9b00ceSrobert       VScaleMax = VScaleMin;
268*7a9b00ceSrobert     return std::pair<unsigned, unsigned>(VScaleMin ? VScaleMin : 1, VScaleMax);
269*7a9b00ceSrobert   }
270*7a9b00ceSrobert 
271*7a9b00ceSrobert   if (VScaleMin > 0) {
272*7a9b00ceSrobert     unsigned VScaleMax = ISAInfo->getMaxVLen() / llvm::RISCV::RVVBitsPerBlock;
273*7a9b00ceSrobert     return std::make_pair(VScaleMin, VScaleMax);
274*7a9b00ceSrobert   }
275*7a9b00ceSrobert 
276*7a9b00ceSrobert   return std::nullopt;
277a0747c9fSpatrick }
278a0747c9fSpatrick 
279e5dd7070Spatrick /// Return true if has this feature, need to sync with handleTargetFeatures.
hasFeature(StringRef Feature) const280e5dd7070Spatrick bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
281e5dd7070Spatrick   bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
282*7a9b00ceSrobert   auto Result = llvm::StringSwitch<std::optional<bool>>(Feature)
283e5dd7070Spatrick                     .Case("riscv", true)
284e5dd7070Spatrick                     .Case("riscv32", !Is64Bit)
285e5dd7070Spatrick                     .Case("riscv64", Is64Bit)
286*7a9b00ceSrobert                     .Case("32bit", !Is64Bit)
287a0747c9fSpatrick                     .Case("64bit", Is64Bit)
288*7a9b00ceSrobert                     .Default(std::nullopt);
289*7a9b00ceSrobert   if (Result)
290*7a9b00ceSrobert     return *Result;
291*7a9b00ceSrobert 
292*7a9b00ceSrobert   if (ISAInfo->isSupportedExtensionFeature(Feature))
293*7a9b00ceSrobert     return ISAInfo->hasExtension(Feature);
294*7a9b00ceSrobert 
295*7a9b00ceSrobert   return false;
296e5dd7070Spatrick }
297e5dd7070Spatrick 
298e5dd7070Spatrick /// Perform initialization based on the user configured set of features.
handleTargetFeatures(std::vector<std::string> & Features,DiagnosticsEngine & Diags)299e5dd7070Spatrick bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
300e5dd7070Spatrick                                            DiagnosticsEngine &Diags) {
301*7a9b00ceSrobert   unsigned XLen = getTriple().isArch64Bit() ? 64 : 32;
302*7a9b00ceSrobert   auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, Features);
303*7a9b00ceSrobert   if (!ParseResult) {
304*7a9b00ceSrobert     std::string Buffer;
305*7a9b00ceSrobert     llvm::raw_string_ostream OutputErrMsg(Buffer);
306*7a9b00ceSrobert     handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
307*7a9b00ceSrobert       OutputErrMsg << ErrMsg.getMessage();
308*7a9b00ceSrobert     });
309*7a9b00ceSrobert     Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
310*7a9b00ceSrobert     return false;
311*7a9b00ceSrobert   } else {
312*7a9b00ceSrobert     ISAInfo = std::move(*ParseResult);
313e5dd7070Spatrick   }
314e5dd7070Spatrick 
315*7a9b00ceSrobert   if (ABI.empty())
316*7a9b00ceSrobert     ABI = ISAInfo->computeDefaultABI().str();
317*7a9b00ceSrobert 
318e5dd7070Spatrick   return true;
319e5dd7070Spatrick }
320ec727ea7Spatrick 
isValidCPUName(StringRef Name) const321*7a9b00ceSrobert bool RISCVTargetInfo::isValidCPUName(StringRef Name) const {
322*7a9b00ceSrobert   bool Is64Bit = getTriple().isArch64Bit();
323*7a9b00ceSrobert   return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), Is64Bit);
324ec727ea7Spatrick }
325ec727ea7Spatrick 
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const326*7a9b00ceSrobert void RISCVTargetInfo::fillValidCPUList(
327ec727ea7Spatrick     SmallVectorImpl<StringRef> &Values) const {
328*7a9b00ceSrobert   bool Is64Bit = getTriple().isArch64Bit();
329*7a9b00ceSrobert   llvm::RISCV::fillValidCPUArchList(Values, Is64Bit);
330ec727ea7Spatrick }
331ec727ea7Spatrick 
isValidTuneCPUName(StringRef Name) const332*7a9b00ceSrobert bool RISCVTargetInfo::isValidTuneCPUName(StringRef Name) const {
333*7a9b00ceSrobert   bool Is64Bit = getTriple().isArch64Bit();
334a0747c9fSpatrick   return llvm::RISCV::checkTuneCPUKind(
335*7a9b00ceSrobert       llvm::RISCV::parseTuneCPUKind(Name, Is64Bit), Is64Bit);
336a0747c9fSpatrick }
337a0747c9fSpatrick 
fillValidTuneCPUList(SmallVectorImpl<StringRef> & Values) const338*7a9b00ceSrobert void RISCVTargetInfo::fillValidTuneCPUList(
339a0747c9fSpatrick     SmallVectorImpl<StringRef> &Values) const {
340*7a9b00ceSrobert   bool Is64Bit = getTriple().isArch64Bit();
341*7a9b00ceSrobert   llvm::RISCV::fillValidTuneCPUArchList(Values, Is64Bit);
342a0747c9fSpatrick }
343