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] ==
'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");
196 if (
ISAInfo->hasExtension(
"a"))
197 Builder.defineMacro(
"__riscv_atomic");
199 if (
ISAInfo->hasExtension(
"zalrsc")) {
200 Builder.defineMacro(
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
201 Builder.defineMacro(
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
202 Builder.defineMacro(
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
204 Builder.defineMacro(
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
208 Builder.defineMacro(
"__riscv_flen", Twine(FLen));
209 Builder.defineMacro(
"__riscv_fdiv");
210 Builder.defineMacro(
"__riscv_fsqrt");
214 Builder.defineMacro(
"__riscv_v_min_vlen", Twine(MinVLen));
215 Builder.defineMacro(
"__riscv_v_elen", Twine(MaxELen));
216 Builder.defineMacro(
"__riscv_v_elen_fp", Twine(MaxELenFp));
219 if (
ISAInfo->hasExtension(
"c"))
220 Builder.defineMacro(
"__riscv_compressed");
222 if (
ISAInfo->hasExtension(
"zve32x"))
223 Builder.defineMacro(
"__riscv_vector");
226 Builder.defineMacro(
"__riscv_v_intrinsic", Twine(
getVersionValue(1, 0)));
229 if (VScale && VScale->first && VScale->first == VScale->second)
230 Builder.defineMacro(
"__riscv_v_fixed_vlen",
231 Twine(VScale->first * llvm::RISCV::RVVBitsPerBlock));
233 if (FastScalarUnalignedAccess)
234 Builder.defineMacro(
"__riscv_misaligned_fast");
236 Builder.defineMacro(
"__riscv_misaligned_avoid");
238 if (
ISAInfo->hasExtension(
"e")) {
240 Builder.defineMacro(
"__riscv_64e");
242 Builder.defineMacro(
"__riscv_32e");
245 if (Opts.CFProtectionReturn &&
ISAInfo->hasExtension(
"zicfiss"))
246 Builder.defineMacro(
"__riscv_shadow_stack");
248 if (Opts.CFProtectionBranch) {
249 auto Scheme = Opts.getCFBranchLabelScheme();
253 Builder.defineMacro(
"__riscv_landing_pad");
255 case CFBranchLabelSchemeKind::Unlabeled:
256 Builder.defineMacro(
"__riscv_landing_pad_unlabeled");
258 case CFBranchLabelSchemeKind::FuncSig:
262 llvm_unreachable(
"default cf-branch-label scheme should already be "
263 "transformed to other scheme");
282#define GET_RISCVV_BUILTIN_STR_TABLE
283#include "clang/Basic/riscv_vector_builtins.inc"
284#undef GET_RISCVV_BUILTIN_STR_TABLE
287static constexpr std::array<Builtin::Info, NumRVVBuiltins>
BuiltinInfos = {
288#define GET_RISCVV_BUILTIN_INFOS
289#include "clang/Basic/riscv_vector_builtins.inc"
290#undef GET_RISCVV_BUILTIN_INFOS
295#define GET_RISCVV_BUILTIN_STR_TABLE
296#include "clang/Basic/riscv_sifive_vector_builtins.inc"
297#undef GET_RISCVV_BUILTIN_STR_TABLE
299static constexpr std::array<Builtin::Info, NumRVVSiFiveBuiltins>
BuiltinInfos =
301#define GET_RISCVV_BUILTIN_INFOS
302#include "clang/Basic/riscv_sifive_vector_builtins.inc"
303#undef GET_RISCVV_BUILTIN_INFOS
308#define GET_RISCVV_BUILTIN_STR_TABLE
309#include "clang/Basic/riscv_andes_vector_builtins.inc"
310#undef GET_RISCVV_BUILTIN_STR_TABLE
312static constexpr std::array<Builtin::Info, NumRVVAndesBuiltins>
BuiltinInfos =
314#define GET_RISCVV_BUILTIN_INFOS
315#include "clang/Basic/riscv_andes_vector_builtins.inc"
316#undef GET_RISCVV_BUILTIN_INFOS
320#define GET_BUILTIN_STR_TABLE
321#include "clang/Basic/BuiltinsRISCV.inc"
322#undef GET_BUILTIN_STR_TABLE
325#define GET_BUILTIN_INFOS
326#include "clang/Basic/BuiltinsRISCV.inc"
327#undef GET_BUILTIN_INFOS
331llvm::SmallVector<Builtin::InfosShard>
343 const std::vector<std::string> &FeaturesVec)
const {
348 Features[
"64bit"] =
true;
351 Features[
"32bit"] =
true;
354 std::vector<std::string> AllFeatures = FeaturesVec;
355 auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, FeaturesVec);
358 llvm::raw_string_ostream OutputErrMsg(Buffer);
359 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
360 OutputErrMsg << ErrMsg.getMessage();
362 Diags.
Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
367 llvm::append_range(AllFeatures, (*ParseResult)->toFeatures());
371std::optional<std::pair<unsigned, unsigned>>
374 llvm::StringMap<bool> *FeatureMap)
const {
376 unsigned VScaleMin =
ISAInfo->getMinVLen() / llvm::RISCV::RVVBitsPerBlock;
378 if (LangOpts.VScaleMin || LangOpts.VScaleMax) {
380 VScaleMin = std::max(VScaleMin, LangOpts.VScaleMin);
381 unsigned VScaleMax = LangOpts.VScaleMax;
382 if (VScaleMax != 0 && VScaleMax < VScaleMin)
383 VScaleMax = VScaleMin;
384 return std::pair<unsigned, unsigned>(VScaleMin ? VScaleMin : 1, VScaleMax);
388 unsigned VScaleMax =
ISAInfo->getMaxVLen() / llvm::RISCV::RVVBitsPerBlock;
389 return std::make_pair(VScaleMin, VScaleMax);
398 auto Result = llvm::StringSwitch<std::optional<bool>>(
Feature)
400 .Case(
"riscv32", !Is64Bit)
401 .Case(
"riscv64", Is64Bit)
402 .Case(
"32bit", !Is64Bit)
403 .Case(
"64bit", Is64Bit)
404 .Case(
"experimental", HasExperimental)
405 .Default(std::nullopt);
415 unsigned XLen =
getTriple().isArch64Bit() ? 64 : 32;
416 auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, Features);
419 llvm::raw_string_ostream OutputErrMsg(Buffer);
420 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
421 OutputErrMsg << ErrMsg.getMessage();
423 Diags.
Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
426 ISAInfo = std::move(*ParseResult);
432 if (
ISAInfo->hasExtension(
"zfh") ||
ISAInfo->hasExtension(
"zhinx"))
435 FastScalarUnalignedAccess =
436 llvm::is_contained(Features,
"+unaligned-scalar-mem");
438 if (llvm::is_contained(Features,
"+experimental"))
439 HasExperimental =
true;
441 if (
ABI ==
"ilp32e" &&
ISAInfo->hasExtension(
"d")) {
442 Diags.
Report(diag::err_invalid_feature_combination)
443 <<
"ILP32E cannot be used with the D ISA extension";
450 bool Is64Bit =
getTriple().isArch64Bit();
451 return llvm::RISCV::parseCPU(Name, Is64Bit);
456 bool Is64Bit =
getTriple().isArch64Bit();
457 llvm::RISCV::fillValidCPUArchList(Values, Is64Bit);
461 bool Is64Bit =
getTriple().isArch64Bit();
462 return llvm::RISCV::parseTuneCPU(Name, Is64Bit);
467 bool Is64Bit =
getTriple().isArch64Bit();
468 llvm::RISCV::fillValidTuneCPUArchList(Values, Is64Bit);
472 auto RII = llvm::RISCVISAInfo::parseArchString(
475 if (llvm::errorToBool(RII.takeError()))
476 llvm_unreachable(
"unsupport rv64i");
478 std::vector<std::string> FeatStrings =
479 (*RII)->toFeatures(
true);
480 llvm::append_range(Features, FeatStrings);
484 std::vector<std::string> &Features) {
485 auto RII = llvm::RISCVISAInfo::parseArchString(
487 if (llvm::errorToBool(RII.takeError())) {
489 Features.push_back(FullArchStr.str());
494 std::vector<std::string> FeatStrings =
495 (*RII)->toFeatures(
true);
496 llvm::append_range(Features, FeatStrings);
502 if (Features ==
"default")
505 Features.split(AttrFeatures,
";");
506 bool FoundArch =
false;
508 auto handleArchExtension = [](StringRef AttrString,
509 std::vector<std::string> &Features) {
511 AttrString.split(Exts,
",");
512 for (
auto Ext : Exts) {
516 StringRef ExtName = Ext.substr(1);
517 std::string TargetFeature =
518 llvm::RISCVISAInfo::getTargetFeatureForExtension(ExtName);
519 if (!TargetFeature.empty())
520 Features.push_back(Ext.front() + TargetFeature);
522 Features.push_back(Ext.str());
526 for (
auto &
Feature : AttrFeatures) {
528 StringRef AttrString =
Feature.split(
"=").second.trim();
530 if (
Feature.starts_with(
"arch=")) {
532 Ret.Features.clear();
534 Ret.Duplicate =
"arch=";
537 if (AttrString.starts_with(
"+")) {
539 handleArchExtension(AttrString, Ret.Features);
544 }
else if (
Feature.starts_with(
"cpu=")) {
545 if (!Ret.CPU.empty())
546 Ret.Duplicate =
"cpu=";
548 Ret.CPU = AttrString;
552 StringRef MarchFromCPU = llvm::RISCV::getMArchFromMcpu(Ret.CPU);
553 if (MarchFromCPU !=
"") {
554 Ret.Features.clear();
558 }
else if (
Feature.starts_with(
"tune=")) {
559 if (!Ret.Tune.empty())
560 Ret.Duplicate =
"tune=";
562 Ret.Tune = AttrString;
563 }
else if (
Feature.starts_with(
"priority")) {
565 }
else if (
Feature.starts_with(
"+")) {
568 handleArchExtension(
Feature, Ret.Features);
579 for (StringRef
Feature : Features) {
580 auto [LHS, RHS] =
Feature.rsplit(
';');
581 if (LHS.consume_front(
"priority="))
583 else if (RHS.consume_front(
"priority="))
588 if (!
Feature.getAsInteger(0, Priority))
589 return llvm::APInt(32, Priority);
592 return llvm::APInt::getZero(32);
621 return -1 != llvm::RISCVISAInfo::getRISCVFeaturesBitsInfo(
Feature).second;
625 return llvm::RISCVISAInfo::isSupportedExtensionFeature(Name);
629 StringRef RegName,
unsigned RegSize,
bool &HasSizeMismatch)
const {
630 if (RegName ==
"ra" || RegName ==
"sp" || RegName ==
"gp" ||
631 RegName ==
"tp" || RegName.starts_with(
"x") || RegName.starts_with(
"a") ||
632 RegName.starts_with(
"s") || RegName.starts_with(
"t")) {
633 unsigned XLen =
getTriple().isArch64Bit() ? 64 : 32;
634 HasSizeMismatch = RegSize != XLen;
642 "__builtin_cpu_is() is only supported for Linux.");
644 return llvm::RISCV::hasValidCPUModel(CPUName);
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 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.
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.
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)