17#include "llvm/ADT/StringSwitch.h"
18#include "llvm/ADT/Twine.h"
19#include "llvm/Support/raw_ostream.h"
20#include "llvm/TargetParser/RISCVTargetParser.h"
30 "x0",
"x1",
"x2",
"x3",
"x4",
"x5",
"x6",
"x7",
31 "x8",
"x9",
"x10",
"x11",
"x12",
"x13",
"x14",
"x15",
32 "x16",
"x17",
"x18",
"x19",
"x20",
"x21",
"x22",
"x23",
33 "x24",
"x25",
"x26",
"x27",
"x28",
"x29",
"x30",
"x31",
36 "f0",
"f1",
"f2",
"f3",
"f4",
"f5",
"f6",
"f7",
37 "f8",
"f9",
"f10",
"f11",
"f12",
"f13",
"f14",
"f15",
38 "f16",
"f17",
"f18",
"f19",
"f20",
"f21",
"f22",
"f23",
39 "f24",
"f25",
"f26",
"f27",
"f28",
"f29",
"f30",
"f31",
42 "v0",
"v1",
"v2",
"v3",
"v4",
"v5",
"v6",
"v7",
43 "v8",
"v9",
"v10",
"v11",
"v12",
"v13",
"v14",
"v15",
44 "v16",
"v17",
"v18",
"v19",
"v20",
"v21",
"v22",
"v23",
45 "v24",
"v25",
"v26",
"v27",
"v28",
"v29",
"v30",
"v31",
48 "fflags",
"frm",
"vtype",
"vl",
"vxsat",
"vxrm",
"sf.vcix_state"
56 {{
"zero"},
"x0"}, {{
"ra"},
"x1"}, {{
"sp"},
"x2"}, {{
"gp"},
"x3"},
57 {{
"tp"},
"x4"}, {{
"t0"},
"x5"}, {{
"t1"},
"x6"}, {{
"t2"},
"x7"},
58 {{
"s0"},
"x8"}, {{
"s1"},
"x9"}, {{
"a0"},
"x10"}, {{
"a1"},
"x11"},
59 {{
"a2"},
"x12"}, {{
"a3"},
"x13"}, {{
"a4"},
"x14"}, {{
"a5"},
"x15"},
60 {{
"a6"},
"x16"}, {{
"a7"},
"x17"}, {{
"s2"},
"x18"}, {{
"s3"},
"x19"},
61 {{
"s4"},
"x20"}, {{
"s5"},
"x21"}, {{
"s6"},
"x22"}, {{
"s7"},
"x23"},
62 {{
"s8"},
"x24"}, {{
"s9"},
"x25"}, {{
"s10"},
"x26"}, {{
"s11"},
"x27"},
63 {{
"t3"},
"x28"}, {{
"t4"},
"x29"}, {{
"t5"},
"x30"}, {{
"t6"},
"x31"},
64 {{
"ft0"},
"f0"}, {{
"ft1"},
"f1"}, {{
"ft2"},
"f2"}, {{
"ft3"},
"f3"},
65 {{
"ft4"},
"f4"}, {{
"ft5"},
"f5"}, {{
"ft6"},
"f6"}, {{
"ft7"},
"f7"},
66 {{
"fs0"},
"f8"}, {{
"fs1"},
"f9"}, {{
"fa0"},
"f10"}, {{
"fa1"},
"f11"},
67 {{
"fa2"},
"f12"}, {{
"fa3"},
"f13"}, {{
"fa4"},
"f14"}, {{
"fa5"},
"f15"},
68 {{
"fa6"},
"f16"}, {{
"fa7"},
"f17"}, {{
"fs2"},
"f18"}, {{
"fs3"},
"f19"},
69 {{
"fs4"},
"f20"}, {{
"fs5"},
"f21"}, {{
"fs6"},
"f22"}, {{
"fs7"},
"f23"},
70 {{
"fs8"},
"f24"}, {{
"fs9"},
"f25"}, {{
"fs10"},
"f26"}, {{
"fs11"},
"f27"},
71 {{
"ft8"},
"f28"}, {{
"ft9"},
"f29"}, {{
"ft10"},
"f30"}, {{
"ft11"},
"f31"}};
106 if (Name[1] ==
'r' || Name[1] ==
'R' || Name[1] ==
'f') {
118 if (Name[1] ==
'r' || Name[1] ==
'd' || Name[1] ==
'm') {
129 switch (*Constraint) {
133 R = std::string(
"^") + std::string(Constraint, 2);
144 return MajorVersion * 1000000 + MinorVersion * 1000;
149 Builder.defineMacro(
"__riscv");
151 Builder.defineMacro(
"__riscv_xlen", Is64Bit ?
"64" :
"32");
153 unsigned FLen =
ISAInfo->getFLen();
154 unsigned MinVLen =
ISAInfo->getMinVLen();
155 unsigned MaxELen =
ISAInfo->getMaxELen();
156 unsigned MaxELenFp =
ISAInfo->getMaxELenFp();
157 if (CodeModel ==
"default")
160 if (CodeModel ==
"small")
161 Builder.defineMacro(
"__riscv_cmodel_medlow");
162 else if (CodeModel ==
"medium")
163 Builder.defineMacro(
"__riscv_cmodel_medany");
164 else if (CodeModel ==
"large")
165 Builder.defineMacro(
"__riscv_cmodel_large");
167 StringRef ABIName =
getABI();
168 if (ABIName ==
"ilp32f" || ABIName ==
"lp64f")
169 Builder.defineMacro(
"__riscv_float_abi_single");
170 else if (ABIName ==
"ilp32d" || ABIName ==
"lp64d")
171 Builder.defineMacro(
"__riscv_float_abi_double");
173 Builder.defineMacro(
"__riscv_float_abi_soft");
175 if (ABIName ==
"ilp32e" || ABIName ==
"lp64e")
176 Builder.defineMacro(
"__riscv_abi_rve");
178 Builder.defineMacro(
"__riscv_arch_test");
180 for (
auto &Extension :
ISAInfo->getExtensions()) {
181 auto ExtName = Extension.first;
182 auto ExtInfo = Extension.second;
184 Builder.defineMacro(Twine(
"__riscv_", ExtName),
188 if (
ISAInfo->hasExtension(
"zmmul"))
189 Builder.defineMacro(
"__riscv_mul");
191 if (
ISAInfo->hasExtension(
"m")) {
192 Builder.defineMacro(
"__riscv_div");
193 Builder.defineMacro(
"__riscv_muldiv");
197 if (
ISAInfo->hasExtension(
"a"))
198 Builder.defineMacro(
"__riscv_atomic");
200 if (
ISAInfo->hasExtension(
"zalrsc")) {
201 Builder.defineMacro(
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
202 Builder.defineMacro(
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
203 Builder.defineMacro(
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
205 Builder.defineMacro(
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
209 Builder.defineMacro(
"__riscv_flen", Twine(FLen));
210 Builder.defineMacro(
"__riscv_fdiv");
211 Builder.defineMacro(
"__riscv_fsqrt");
215 Builder.defineMacro(
"__riscv_v_min_vlen", Twine(MinVLen));
216 Builder.defineMacro(
"__riscv_v_elen", Twine(MaxELen));
217 Builder.defineMacro(
"__riscv_v_elen_fp", Twine(MaxELenFp));
220 if (
ISAInfo->hasExtension(
"c"))
221 Builder.defineMacro(
"__riscv_compressed");
223 if (
ISAInfo->hasExtension(
"zve32x"))
224 Builder.defineMacro(
"__riscv_vector");
227 Builder.defineMacro(
"__riscv_v_intrinsic", Twine(
getVersionValue(1, 0)));
230 if (VScale && VScale->first && VScale->first == VScale->second)
231 Builder.defineMacro(
"__riscv_v_fixed_vlen",
232 Twine(VScale->first * llvm::RISCV::RVVBitsPerBlock));
234 if (FastScalarUnalignedAccess)
235 Builder.defineMacro(
"__riscv_misaligned_fast");
237 Builder.defineMacro(
"__riscv_misaligned_avoid");
239 if (
ISAInfo->hasExtension(
"e")) {
241 Builder.defineMacro(
"__riscv_64e");
243 Builder.defineMacro(
"__riscv_32e");
246 if (Opts.CFProtectionReturn &&
ISAInfo->hasExtension(
"zicfiss"))
247 Builder.defineMacro(
"__riscv_shadow_stack");
249 if (Opts.CFProtectionBranch) {
250 auto Scheme = Opts.getCFBranchLabelScheme();
254 Builder.defineMacro(
"__riscv_landing_pad");
256 case CFBranchLabelSchemeKind::Unlabeled:
257 Builder.defineMacro(
"__riscv_landing_pad_unlabeled");
259 case CFBranchLabelSchemeKind::FuncSig:
263 llvm_unreachable(
"default cf-branch-label scheme should already be "
264 "transformed to other scheme");
283#define GET_RISCVV_BUILTIN_STR_TABLE
284#include "clang/Basic/riscv_vector_builtins.inc"
285#undef GET_RISCVV_BUILTIN_STR_TABLE
288static constexpr std::array<Builtin::Info, NumRVVBuiltins>
BuiltinInfos = {
289#define GET_RISCVV_BUILTIN_INFOS
290#include "clang/Basic/riscv_vector_builtins.inc"
291#undef GET_RISCVV_BUILTIN_INFOS
296#define GET_RISCVV_BUILTIN_STR_TABLE
297#include "clang/Basic/riscv_sifive_vector_builtins.inc"
298#undef GET_RISCVV_BUILTIN_STR_TABLE
300static constexpr std::array<Builtin::Info, NumRVVSiFiveBuiltins>
BuiltinInfos =
302#define GET_RISCVV_BUILTIN_INFOS
303#include "clang/Basic/riscv_sifive_vector_builtins.inc"
304#undef GET_RISCVV_BUILTIN_INFOS
309#define GET_RISCVV_BUILTIN_STR_TABLE
310#include "clang/Basic/riscv_andes_vector_builtins.inc"
311#undef GET_RISCVV_BUILTIN_STR_TABLE
313static constexpr std::array<Builtin::Info, NumRVVAndesBuiltins>
BuiltinInfos =
315#define GET_RISCVV_BUILTIN_INFOS
316#include "clang/Basic/riscv_andes_vector_builtins.inc"
317#undef GET_RISCVV_BUILTIN_INFOS
321#define GET_BUILTIN_STR_TABLE
322#include "clang/Basic/BuiltinsRISCV.inc"
323#undef GET_BUILTIN_STR_TABLE
326#define GET_BUILTIN_INFOS
327#include "clang/Basic/BuiltinsRISCV.inc"
328#undef GET_BUILTIN_INFOS
332llvm::SmallVector<Builtin::InfosShard>
344 const std::vector<std::string> &FeaturesVec)
const {
349 Features[
"64bit"] =
true;
352 Features[
"32bit"] =
true;
355 std::vector<std::string> AllFeatures = FeaturesVec;
356 auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, FeaturesVec);
359 llvm::raw_string_ostream OutputErrMsg(Buffer);
360 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
361 OutputErrMsg << ErrMsg.getMessage();
363 Diags.
Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
368 llvm::append_range(AllFeatures, (*ParseResult)->toFeatures());
372std::optional<std::pair<unsigned, unsigned>>
375 llvm::StringMap<bool> *FeatureMap)
const {
377 unsigned VScaleMin =
ISAInfo->getMinVLen() / llvm::RISCV::RVVBitsPerBlock;
379 if (LangOpts.VScaleMin || LangOpts.VScaleMax) {
381 VScaleMin = std::max(VScaleMin, LangOpts.VScaleMin);
382 unsigned VScaleMax = LangOpts.VScaleMax;
383 if (VScaleMax != 0 && VScaleMax < VScaleMin)
384 VScaleMax = VScaleMin;
385 return std::pair<unsigned, unsigned>(VScaleMin ? VScaleMin : 1, VScaleMax);
389 unsigned VScaleMax =
ISAInfo->getMaxVLen() / llvm::RISCV::RVVBitsPerBlock;
390 return std::make_pair(VScaleMin, VScaleMax);
399 auto Result = llvm::StringSwitch<std::optional<bool>>(
Feature)
401 .Case(
"riscv32", !Is64Bit)
402 .Case(
"riscv64", Is64Bit)
403 .Case(
"32bit", !Is64Bit)
404 .Case(
"64bit", Is64Bit)
405 .Case(
"experimental", HasExperimental)
406 .Default(std::nullopt);
416 unsigned XLen =
getTriple().isArch64Bit() ? 64 : 32;
417 auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, Features);
420 llvm::raw_string_ostream OutputErrMsg(Buffer);
421 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
422 OutputErrMsg << ErrMsg.getMessage();
424 Diags.
Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
427 ISAInfo = std::move(*ParseResult);
433 if (
ISAInfo->hasExtension(
"zfh") ||
ISAInfo->hasExtension(
"zhinx"))
436 FastScalarUnalignedAccess =
437 llvm::is_contained(Features,
"+unaligned-scalar-mem");
439 if (llvm::is_contained(Features,
"+experimental"))
440 HasExperimental =
true;
442 if (
ABI ==
"ilp32e" &&
ISAInfo->hasExtension(
"d")) {
443 Diags.
Report(diag::err_invalid_feature_combination)
444 <<
"ILP32E cannot be used with the D ISA extension";
451 bool Is64Bit =
getTriple().isArch64Bit();
452 return llvm::RISCV::parseCPU(Name, Is64Bit);
457 bool Is64Bit =
getTriple().isArch64Bit();
458 llvm::RISCV::fillValidCPUArchList(Values, Is64Bit);
462 bool Is64Bit =
getTriple().isArch64Bit();
463 return llvm::RISCV::parseTuneCPU(Name, Is64Bit);
468 bool Is64Bit =
getTriple().isArch64Bit();
469 llvm::RISCV::fillValidTuneCPUArchList(Values, Is64Bit);
473 auto RII = llvm::RISCVISAInfo::parseArchString(
476 if (llvm::errorToBool(RII.takeError()))
477 llvm_unreachable(
"unsupport rv64i");
479 std::vector<std::string> FeatStrings =
480 (*RII)->toFeatures(
true);
481 llvm::append_range(Features, FeatStrings);
485 std::vector<std::string> &Features) {
486 auto RII = llvm::RISCVISAInfo::parseArchString(
488 if (llvm::errorToBool(RII.takeError())) {
490 Features.push_back(FullArchStr.str());
495 std::vector<std::string> FeatStrings =
496 (*RII)->toFeatures(
true);
497 llvm::append_range(Features, FeatStrings);
503 if (Features ==
"default")
506 Features.split(AttrFeatures,
";");
507 bool FoundArch =
false;
509 auto handleArchExtension = [](StringRef AttrString,
510 std::vector<std::string> &Features) {
512 AttrString.split(Exts,
",");
513 for (
auto Ext : Exts) {
517 StringRef ExtName = Ext.substr(1);
518 std::string TargetFeature =
519 llvm::RISCVISAInfo::getTargetFeatureForExtension(ExtName);
520 if (!TargetFeature.empty())
521 Features.push_back(Ext.front() + TargetFeature);
523 Features.push_back(Ext.str());
527 for (
auto &
Feature : AttrFeatures) {
529 StringRef AttrString =
Feature.split(
"=").second.trim();
531 if (
Feature.starts_with(
"arch=")) {
533 Ret.Features.clear();
535 Ret.Duplicate =
"arch=";
538 if (AttrString.starts_with(
"+")) {
540 handleArchExtension(AttrString, Ret.Features);
545 }
else if (
Feature.starts_with(
"cpu=")) {
546 if (!Ret.CPU.empty())
547 Ret.Duplicate =
"cpu=";
549 Ret.CPU = AttrString;
553 StringRef MarchFromCPU = llvm::RISCV::getMArchFromMcpu(Ret.CPU);
554 if (MarchFromCPU !=
"") {
555 Ret.Features.clear();
559 }
else if (
Feature.starts_with(
"tune=")) {
560 if (!Ret.Tune.empty())
561 Ret.Duplicate =
"tune=";
563 Ret.Tune = AttrString;
564 }
else if (
Feature.starts_with(
"priority")) {
566 }
else if (
Feature.starts_with(
"+")) {
569 handleArchExtension(
Feature, Ret.Features);
580 for (StringRef
Feature : Features) {
581 auto [LHS, RHS] =
Feature.rsplit(
';');
582 if (LHS.consume_front(
"priority="))
584 else if (RHS.consume_front(
"priority="))
589 if (!
Feature.getAsInteger(0, Priority))
590 return llvm::APInt(32, Priority);
593 return llvm::APInt::getZero(32);
622 return -1 != llvm::RISCVISAInfo::getRISCVFeaturesBitsInfo(
Feature).second;
626 return llvm::RISCVISAInfo::isSupportedExtensionFeature(Name);
630 StringRef RegName,
unsigned RegSize,
bool &HasSizeMismatch)
const {
631 if (RegName ==
"ra" || RegName ==
"sp" || RegName ==
"gp" ||
632 RegName ==
"tp" || RegName.starts_with(
"x") || RegName.starts_with(
"a") ||
633 RegName.starts_with(
"s") || RegName.starts_with(
"t")) {
634 unsigned XLen =
getTriple().isArch64Bit() ? 64 : 32;
635 HasSizeMismatch = RegSize != XLen;
643 "__builtin_cpu_is() is only supported for Linux.");
645 return llvm::RISCV::hasValidCPUModel(CPUName);
654 Diags.
Report(diag::err_opt_not_valid_without_opt)
655 <<
"-fcf-protection=branch"
656 << (Twine(
"-mcf-branch-label-scheme=") +
660 case CFBranchLabelSchemeKind::Unlabeled:
662 case CFBranchLabelSchemeKind::FuncSig:
663 Diags.
Report(diag::err_opt_unsupported_with_suggest)
664 << (Twine(
"-mcf-branch-label-scheme=") +
667 << (Twine(
"-mcf-branch-label-scheme=") +
Defines the Diagnostic-related interfaces.
static constexpr llvm::StringTable BuiltinStrings
static constexpr int NumRISCVBuiltins
static constexpr int NumRVVAndesBuiltins
static constexpr int NumRVVBuiltins
static void populateNegativeRISCVFeatures(std::vector< std::string > &Features)
static constexpr int NumRVVSiFiveBuiltins
static unsigned getVersionValue(unsigned MajorVersion, unsigned MinorVersion)
static void handleFullArchString(StringRef FullArchStr, std::vector< std::string > &Features)
static constexpr Builtin::Info BuiltinInfos[]
static constexpr unsigned NumBuiltins
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 checkCFBranchLabelSchemeSupported(const CFBranchLabelSchemeKind Scheme, DiagnosticsEngine &Diags) const
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 -----------------------—===//
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.
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.
llvm::APInt getFMVPriority(ArrayRef< StringRef > Features) const override
bool validateCpuSupports(StringRef Feature) const override
std::optional< std::pair< unsigned, unsigned > > getVScaleRange(const LangOptions &LangOpts, ArmStreamingKind Mode, llvm::StringMap< bool > *FeatureMap=nullptr) const override
Returns target-specific min and max values VScale_Range.
StringRef getABI() const override
Get the ABI currently in use.
bool checkCFBranchLabelSchemeSupported(const CFBranchLabelSchemeKind Scheme, DiagnosticsEngine &Diags) const override
CFBranchLabelSchemeKind getDefaultCFBranchLabelScheme() const override
Get the target default CFBranchLabelScheme scheme.
bool handleTargetFeatures(std::vector< std::string > &Features, DiagnosticsEngine &Diags) override
Perform initialization based on the user configured set of features.
llvm::SmallVector< Builtin::InfosShard > getTargetBuiltins() const override
Return information about target-specific builtins for the current primary target, and info about whic...
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.
static constexpr std::array< Builtin::Info, NumRVVAndesBuiltins > BuiltinInfos
static constexpr std::array< Builtin::Info, NumRVVSiFiveBuiltins > BuiltinInfos
static constexpr std::array< Builtin::Info, NumRVVBuiltins > BuiltinInfos
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.
static const char * getCFBranchLabelSchemeFlagVal(const CFBranchLabelSchemeKind Scheme)
CallingConv
CallingConv - Specifies the calling convention that a function uses.
bool IsArmStreamingFunction(const FunctionDecl *FD, bool IncludeLocallyStreaming)
Returns whether the given FunctionDecl has an __arm[_locally]_streaming attribute.
The info used to represent each builtin.
Contains information gathered from parsing the contents of TargetAttr.
void setRequiresImmediate(int Min, int Max)