17#include "llvm/ADT/StringSwitch.h"
18#include "llvm/Support/raw_ostream.h"
19#include "llvm/TargetParser/RISCVTargetParser.h"
29 "x0",
"x1",
"x2",
"x3",
"x4",
"x5",
"x6",
"x7",
30 "x8",
"x9",
"x10",
"x11",
"x12",
"x13",
"x14",
"x15",
31 "x16",
"x17",
"x18",
"x19",
"x20",
"x21",
"x22",
"x23",
32 "x24",
"x25",
"x26",
"x27",
"x28",
"x29",
"x30",
"x31",
35 "f0",
"f1",
"f2",
"f3",
"f4",
"f5",
"f6",
"f7",
36 "f8",
"f9",
"f10",
"f11",
"f12",
"f13",
"f14",
"f15",
37 "f16",
"f17",
"f18",
"f19",
"f20",
"f21",
"f22",
"f23",
38 "f24",
"f25",
"f26",
"f27",
"f28",
"f29",
"f30",
"f31",
41 "v0",
"v1",
"v2",
"v3",
"v4",
"v5",
"v6",
"v7",
42 "v8",
"v9",
"v10",
"v11",
"v12",
"v13",
"v14",
"v15",
43 "v16",
"v17",
"v18",
"v19",
"v20",
"v21",
"v22",
"v23",
44 "v24",
"v25",
"v26",
"v27",
"v28",
"v29",
"v30",
"v31",
47 "fflags",
"frm",
"vtype",
"vl",
"vxsat",
"vxrm",
"sf.vcix_state"
55 {{
"zero"},
"x0"}, {{
"ra"},
"x1"}, {{
"sp"},
"x2"}, {{
"gp"},
"x3"},
56 {{
"tp"},
"x4"}, {{
"t0"},
"x5"}, {{
"t1"},
"x6"}, {{
"t2"},
"x7"},
57 {{
"s0"},
"x8"}, {{
"s1"},
"x9"}, {{
"a0"},
"x10"}, {{
"a1"},
"x11"},
58 {{
"a2"},
"x12"}, {{
"a3"},
"x13"}, {{
"a4"},
"x14"}, {{
"a5"},
"x15"},
59 {{
"a6"},
"x16"}, {{
"a7"},
"x17"}, {{
"s2"},
"x18"}, {{
"s3"},
"x19"},
60 {{
"s4"},
"x20"}, {{
"s5"},
"x21"}, {{
"s6"},
"x22"}, {{
"s7"},
"x23"},
61 {{
"s8"},
"x24"}, {{
"s9"},
"x25"}, {{
"s10"},
"x26"}, {{
"s11"},
"x27"},
62 {{
"t3"},
"x28"}, {{
"t4"},
"x29"}, {{
"t5"},
"x30"}, {{
"t6"},
"x31"},
63 {{
"ft0"},
"f0"}, {{
"ft1"},
"f1"}, {{
"ft2"},
"f2"}, {{
"ft3"},
"f3"},
64 {{
"ft4"},
"f4"}, {{
"ft5"},
"f5"}, {{
"ft6"},
"f6"}, {{
"ft7"},
"f7"},
65 {{
"fs0"},
"f8"}, {{
"fs1"},
"f9"}, {{
"fa0"},
"f10"}, {{
"fa1"},
"f11"},
66 {{
"fa2"},
"f12"}, {{
"fa3"},
"f13"}, {{
"fa4"},
"f14"}, {{
"fa5"},
"f15"},
67 {{
"fa6"},
"f16"}, {{
"fa7"},
"f17"}, {{
"fs2"},
"f18"}, {{
"fs3"},
"f19"},
68 {{
"fs4"},
"f20"}, {{
"fs5"},
"f21"}, {{
"fs6"},
"f22"}, {{
"fs7"},
"f23"},
69 {{
"fs8"},
"f24"}, {{
"fs9"},
"f25"}, {{
"fs10"},
"f26"}, {{
"fs11"},
"f27"},
70 {{
"ft8"},
"f28"}, {{
"ft9"},
"f29"}, {{
"ft10"},
"f30"}, {{
"ft11"},
"f31"}};
105 if (Name[1] ==
'r' || Name[1] ==
'f') {
117 if (Name[1] ==
'r' || Name[1] ==
'd' || Name[1] ==
'm') {
128 switch (*Constraint) {
132 R = std::string(
"^") + std::string(Constraint, 2);
143 return MajorVersion * 1000000 + MinorVersion * 1000;
148 Builder.defineMacro(
"__riscv");
150 Builder.defineMacro(
"__riscv_xlen", Is64Bit ?
"64" :
"32");
152 unsigned FLen =
ISAInfo->getFLen();
153 unsigned MinVLen =
ISAInfo->getMinVLen();
154 unsigned MaxELen =
ISAInfo->getMaxELen();
155 unsigned MaxELenFp =
ISAInfo->getMaxELenFp();
156 if (CodeModel ==
"default")
159 if (CodeModel ==
"small")
160 Builder.defineMacro(
"__riscv_cmodel_medlow");
161 else if (CodeModel ==
"medium")
162 Builder.defineMacro(
"__riscv_cmodel_medany");
163 else if (CodeModel ==
"large")
164 Builder.defineMacro(
"__riscv_cmodel_large");
166 StringRef ABIName =
getABI();
167 if (ABIName ==
"ilp32f" || ABIName ==
"lp64f")
168 Builder.defineMacro(
"__riscv_float_abi_single");
169 else if (ABIName ==
"ilp32d" || ABIName ==
"lp64d")
170 Builder.defineMacro(
"__riscv_float_abi_double");
172 Builder.defineMacro(
"__riscv_float_abi_soft");
174 if (ABIName ==
"ilp32e" || ABIName ==
"lp64e")
175 Builder.defineMacro(
"__riscv_abi_rve");
177 Builder.defineMacro(
"__riscv_arch_test");
179 for (
auto &Extension :
ISAInfo->getExtensions()) {
180 auto ExtName = Extension.first;
181 auto ExtInfo = Extension.second;
183 Builder.defineMacro(Twine(
"__riscv_", ExtName),
187 if (
ISAInfo->hasExtension(
"zmmul"))
188 Builder.defineMacro(
"__riscv_mul");
190 if (
ISAInfo->hasExtension(
"m")) {
191 Builder.defineMacro(
"__riscv_div");
192 Builder.defineMacro(
"__riscv_muldiv");
195 if (
ISAInfo->hasExtension(
"a")) {
196 Builder.defineMacro(
"__riscv_atomic");
197 Builder.defineMacro(
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
198 Builder.defineMacro(
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
199 Builder.defineMacro(
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
201 Builder.defineMacro(
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
205 Builder.defineMacro(
"__riscv_flen", Twine(FLen));
206 Builder.defineMacro(
"__riscv_fdiv");
207 Builder.defineMacro(
"__riscv_fsqrt");
211 Builder.defineMacro(
"__riscv_v_min_vlen", Twine(MinVLen));
212 Builder.defineMacro(
"__riscv_v_elen", Twine(MaxELen));
213 Builder.defineMacro(
"__riscv_v_elen_fp", Twine(MaxELenFp));
216 if (
ISAInfo->hasExtension(
"c"))
217 Builder.defineMacro(
"__riscv_compressed");
219 if (
ISAInfo->hasExtension(
"zve32x"))
220 Builder.defineMacro(
"__riscv_vector");
223 Builder.defineMacro(
"__riscv_v_intrinsic", Twine(
getVersionValue(1, 0)));
226 if (VScale && VScale->first && VScale->first == VScale->second)
227 Builder.defineMacro(
"__riscv_v_fixed_vlen",
228 Twine(VScale->first * llvm::RISCV::RVVBitsPerBlock));
230 if (FastScalarUnalignedAccess)
231 Builder.defineMacro(
"__riscv_misaligned_fast");
233 Builder.defineMacro(
"__riscv_misaligned_avoid");
235 if (
ISAInfo->hasExtension(
"e")) {
237 Builder.defineMacro(
"__riscv_64e");
239 Builder.defineMacro(
"__riscv_32e");
244#define BUILTIN(ID, TYPE, ATTRS) \
245 {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
246#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
247 {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
248#include "clang/Basic/BuiltinsRISCVVector.def"
249#define BUILTIN(ID, TYPE, ATTRS) \
250 {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
251#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
252 {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
253#include "clang/Basic/BuiltinsRISCV.inc"
263 const std::vector<std::string> &FeaturesVec)
const {
268 Features[
"64bit"] =
true;
271 Features[
"32bit"] =
true;
274 std::vector<std::string> AllFeatures = FeaturesVec;
275 auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, FeaturesVec);
278 llvm::raw_string_ostream OutputErrMsg(Buffer);
279 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
280 OutputErrMsg << ErrMsg.getMessage();
282 Diags.
Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
287 llvm::append_range(AllFeatures, (*ParseResult)->toFeatures());
291std::optional<std::pair<unsigned, unsigned>>
294 unsigned VScaleMin =
ISAInfo->getMinVLen() / llvm::RISCV::RVVBitsPerBlock;
296 if (LangOpts.VScaleMin || LangOpts.VScaleMax) {
298 VScaleMin = std::max(VScaleMin, LangOpts.VScaleMin);
299 unsigned VScaleMax = LangOpts.VScaleMax;
300 if (VScaleMax != 0 && VScaleMax < VScaleMin)
301 VScaleMax = VScaleMin;
302 return std::pair<unsigned, unsigned>(VScaleMin ? VScaleMin : 1, VScaleMax);
306 unsigned VScaleMax =
ISAInfo->getMaxVLen() / llvm::RISCV::RVVBitsPerBlock;
307 return std::make_pair(VScaleMin, VScaleMax);
316 auto Result = llvm::StringSwitch<std::optional<bool>>(Feature)
318 .Case(
"riscv32", !Is64Bit)
319 .Case(
"riscv64", Is64Bit)
320 .Case(
"32bit", !Is64Bit)
321 .Case(
"64bit", Is64Bit)
322 .Case(
"experimental", HasExperimental)
323 .Default(std::nullopt);
327 return ISAInfo->hasExtension(Feature);
333 unsigned XLen =
getTriple().isArch64Bit() ? 64 : 32;
334 auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, Features);
337 llvm::raw_string_ostream OutputErrMsg(Buffer);
338 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
339 OutputErrMsg << ErrMsg.getMessage();
341 Diags.
Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
344 ISAInfo = std::move(*ParseResult);
350 if (
ISAInfo->hasExtension(
"zfh") ||
ISAInfo->hasExtension(
"zhinx"))
353 FastScalarUnalignedAccess =
354 llvm::is_contained(Features,
"+unaligned-scalar-mem");
356 if (llvm::is_contained(Features,
"+experimental"))
357 HasExperimental =
true;
359 if (
ABI ==
"ilp32e" &&
ISAInfo->hasExtension(
"d")) {
360 Diags.
Report(diag::err_invalid_feature_combination)
361 <<
"ILP32E cannot be used with the D ISA extension";
368 bool Is64Bit =
getTriple().isArch64Bit();
369 return llvm::RISCV::parseCPU(Name, Is64Bit);
374 bool Is64Bit =
getTriple().isArch64Bit();
375 llvm::RISCV::fillValidCPUArchList(Values, Is64Bit);
379 bool Is64Bit =
getTriple().isArch64Bit();
380 return llvm::RISCV::parseTuneCPU(Name, Is64Bit);
385 bool Is64Bit =
getTriple().isArch64Bit();
386 llvm::RISCV::fillValidTuneCPUArchList(Values, Is64Bit);
390 auto RII = llvm::RISCVISAInfo::parseArchString(
393 if (llvm::errorToBool(RII.takeError()))
394 llvm_unreachable(
"unsupport rv64i");
396 std::vector<std::string> FeatStrings =
397 (*RII)->toFeatures(
true);
398 Features.insert(Features.end(), FeatStrings.begin(), FeatStrings.end());
402 std::vector<std::string> &Features) {
403 auto RII = llvm::RISCVISAInfo::parseArchString(
405 if (llvm::errorToBool(RII.takeError())) {
407 Features.push_back(FullArchStr.str());
412 std::vector<std::string> FeatStrings =
413 (*RII)->toFeatures(
true);
414 Features.insert(Features.end(), FeatStrings.begin(), FeatStrings.end());
420 if (Features ==
"default")
423 Features.split(AttrFeatures,
";");
424 bool FoundArch =
false;
426 auto handleArchExtension = [](StringRef AttrString,
427 std::vector<std::string> &Features) {
429 AttrString.split(Exts,
",");
430 for (
auto Ext : Exts) {
434 StringRef ExtName = Ext.substr(1);
435 std::string TargetFeature =
436 llvm::RISCVISAInfo::getTargetFeatureForExtension(ExtName);
437 if (!TargetFeature.empty())
438 Features.push_back(Ext.front() + TargetFeature);
440 Features.push_back(Ext.str());
444 for (
auto &Feature : AttrFeatures) {
445 Feature = Feature.trim();
446 StringRef AttrString = Feature.split(
"=").second.trim();
448 if (Feature.starts_with(
"arch=")) {
450 Ret.Features.clear();
452 Ret.Duplicate =
"arch=";
455 if (AttrString.starts_with(
"+")) {
457 handleArchExtension(AttrString, Ret.Features);
462 }
else if (Feature.starts_with(
"cpu=")) {
463 if (!Ret.CPU.empty())
464 Ret.Duplicate =
"cpu=";
466 Ret.CPU = AttrString;
470 StringRef MarchFromCPU = llvm::RISCV::getMArchFromMcpu(Ret.CPU);
471 if (MarchFromCPU !=
"") {
472 Ret.Features.clear();
476 }
else if (Feature.starts_with(
"tune=")) {
477 if (!Ret.Tune.empty())
478 Ret.Duplicate =
"tune=";
480 Ret.Tune = AttrString;
481 }
else if (Feature.starts_with(
"priority")) {
483 }
else if (Feature.starts_with(
"+")) {
486 handleArchExtension(Feature, Ret.Features);
496 for (StringRef Feature : Features) {
497 auto [LHS, RHS] = Feature.rsplit(
';');
498 if (LHS.consume_front(
"priority="))
500 else if (RHS.consume_front(
"priority="))
505 if (!Feature.getAsInteger(0,
Priority))
526 return -1 != llvm::RISCVISAInfo::getRISCVFeaturesBitsInfo(Feature).second;
530 return llvm::RISCVISAInfo::isSupportedExtensionFeature(Name);
534 StringRef RegName,
unsigned RegSize,
bool &HasSizeMismatch)
const {
535 if (RegName ==
"ra" || RegName ==
"sp" || RegName ==
"gp" ||
536 RegName ==
"tp" || RegName.starts_with(
"x") || RegName.starts_with(
"a") ||
537 RegName.starts_with(
"s") || RegName.starts_with(
"t")) {
538 unsigned XLen =
getTriple().isArch64Bit() ? 64 : 32;
539 HasSizeMismatch = RegSize != XLen;
547 "__builtin_cpu_is() is only supported for Linux.");
549 return llvm::RISCV::hasValidCPUModel(CPUName);
Defines the Diagnostic-related interfaces.
static void populateNegativeRISCVFeatures(std::vector< std::string > &Features)
static unsigned getVersionValue(unsigned MajorVersion, unsigned MinorVersion)
static void handleFullArchString(StringRef FullArchStr, std::vector< std::string > &Features)
static constexpr Builtin::Info BuiltinInfo[]
Defines the clang::MacroBuilder utility class.
Enumerates target-specific builtins in their own namespaces within namespace clang.
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
TargetOptions & getTargetOpts() const
Retrieve the target options.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
virtual bool initFeatureMap(llvm::StringMap< bool > &Features, DiagnosticsEngine &Diags, StringRef CPU, const std::vector< std::string > &FeatureVec) const
Initialize the map with the default set of target features for the CPU this should include all legal ...
virtual std::string convertConstraint(const char *&Constraint) const
bool isValidFeatureName(StringRef Name) const override
Determine whether this TargetInfo supports the given feature.
std::string convertConstraint(const char *&Constraint) const override
void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override
===-— Other target property query methods -----------------------—===//
ArrayRef< Builtin::Info > getTargetBuiltins() const override
Return information about target-specific builtins for the current primary target, and info about whic...
bool validateAsmConstraint(const char *&Name, TargetInfo::ConstraintInfo &Info) const override
bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize, bool &HasSizeMismatch) const override
Validate register name used for global register variables.
bool initFeatureMap(llvm::StringMap< bool > &Features, DiagnosticsEngine &Diags, StringRef CPU, const std::vector< std::string > &FeaturesVec) const override
Initialize the map with the default set of target features for the CPU this should include all legal ...
std::unique_ptr< llvm::RISCVISAInfo > ISAInfo
void fillValidTuneCPUList(SmallVectorImpl< StringRef > &Values) const override
Fill a SmallVectorImpl with the valid values for tuning CPU.
bool isValidTuneCPUName(StringRef Name) const override
Determine whether this TargetInfo supports the given CPU name for tuning.
std::optional< std::pair< unsigned, unsigned > > getVScaleRange(const LangOptions &LangOpts) const override
Returns target-specific min and max values VScale_Range.
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override
Determines whether a given calling convention is valid for the target.
ArrayRef< const char * > getGCCRegNames() const override
ArrayRef< TargetInfo::GCCRegAlias > getGCCRegAliases() const override
void fillValidCPUList(SmallVectorImpl< StringRef > &Values) const override
Fill a SmallVectorImpl with the valid values to setCPU.
bool validateCpuSupports(StringRef Feature) const override
StringRef getABI() const override
Get the ABI currently in use.
bool handleTargetFeatures(std::vector< std::string > &Features, DiagnosticsEngine &Diags) override
Perform initialization based on the user configured set of features.
ParsedTargetAttr parseTargetAttr(StringRef Str) const override
bool hasFeature(StringRef Feature) const override
Return true if has this feature, need to sync with handleTargetFeatures.
bool validateCpuIs(StringRef CPUName) const override
bool isValidCPUName(StringRef Name) const override
Determine whether this TargetInfo supports the given CPU name.
unsigned getFMVPriority(ArrayRef< StringRef > Features) const override
static const char *const GCCRegNames[]
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
CallingConv
CallingConv - Specifies the calling convention that a function uses.
Contains information gathered from parsing the contents of TargetAttr.
void setRequiresImmediate(int Min, int Max)