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");
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");
242 if (Opts.CFProtectionReturn &&
ISAInfo->hasExtension(
"zicfiss"))
243 Builder.defineMacro(
"__riscv_shadow_stack");
245 if (Opts.CFProtectionBranch) {
246 auto Scheme = Opts.getCFBranchLabelScheme();
250 Builder.defineMacro(
"__riscv_landing_pad");
252 case CFBranchLabelSchemeKind::Unlabeled:
253 Builder.defineMacro(
"__riscv_landing_pad_unlabeled");
255 case CFBranchLabelSchemeKind::FuncSig:
259 llvm_unreachable(
"default cf-branch-label scheme should already be "
260 "transformed to other scheme");
279#define GET_RISCVV_BUILTIN_STR_TABLE
280#include "clang/Basic/riscv_vector_builtins.inc"
281#undef GET_RISCVV_BUILTIN_STR_TABLE
284static constexpr std::array<Builtin::Info, NumRVVBuiltins>
BuiltinInfos = {
285#define GET_RISCVV_BUILTIN_INFOS
286#include "clang/Basic/riscv_vector_builtins.inc"
287#undef GET_RISCVV_BUILTIN_INFOS
292#define GET_RISCVV_BUILTIN_STR_TABLE
293#include "clang/Basic/riscv_sifive_vector_builtins.inc"
294#undef GET_RISCVV_BUILTIN_STR_TABLE
296static constexpr std::array<Builtin::Info, NumRVVSiFiveBuiltins>
BuiltinInfos =
298#define GET_RISCVV_BUILTIN_INFOS
299#include "clang/Basic/riscv_sifive_vector_builtins.inc"
300#undef GET_RISCVV_BUILTIN_INFOS
305#define GET_RISCVV_BUILTIN_STR_TABLE
306#include "clang/Basic/riscv_andes_vector_builtins.inc"
307#undef GET_RISCVV_BUILTIN_STR_TABLE
309static constexpr std::array<Builtin::Info, NumRVVAndesBuiltins>
BuiltinInfos =
311#define GET_RISCVV_BUILTIN_INFOS
312#include "clang/Basic/riscv_andes_vector_builtins.inc"
313#undef GET_RISCVV_BUILTIN_INFOS
317#define GET_BUILTIN_STR_TABLE
318#include "clang/Basic/BuiltinsRISCV.inc"
319#undef GET_BUILTIN_STR_TABLE
322#define GET_BUILTIN_INFOS
323#include "clang/Basic/BuiltinsRISCV.inc"
324#undef GET_BUILTIN_INFOS
328llvm::SmallVector<Builtin::InfosShard>
340 const std::vector<std::string> &FeaturesVec)
const {
345 Features[
"64bit"] =
true;
348 Features[
"32bit"] =
true;
351 std::vector<std::string> AllFeatures = FeaturesVec;
352 auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, FeaturesVec);
355 llvm::raw_string_ostream OutputErrMsg(Buffer);
356 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
357 OutputErrMsg << ErrMsg.getMessage();
359 Diags.
Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
364 llvm::append_range(AllFeatures, (*ParseResult)->toFeatures());
368std::optional<std::pair<unsigned, unsigned>>
371 llvm::StringMap<bool> *FeatureMap)
const {
373 unsigned VScaleMin =
ISAInfo->getMinVLen() / llvm::RISCV::RVVBitsPerBlock;
375 if (LangOpts.VScaleMin || LangOpts.VScaleMax) {
377 VScaleMin = std::max(VScaleMin, LangOpts.VScaleMin);
378 unsigned VScaleMax = LangOpts.VScaleMax;
379 if (VScaleMax != 0 && VScaleMax < VScaleMin)
380 VScaleMax = VScaleMin;
381 return std::pair<unsigned, unsigned>(VScaleMin ? VScaleMin : 1, VScaleMax);
385 unsigned VScaleMax =
ISAInfo->getMaxVLen() / llvm::RISCV::RVVBitsPerBlock;
386 return std::make_pair(VScaleMin, VScaleMax);
395 auto Result = llvm::StringSwitch<std::optional<bool>>(
Feature)
397 .Case(
"riscv32", !Is64Bit)
398 .Case(
"riscv64", Is64Bit)
399 .Case(
"32bit", !Is64Bit)
400 .Case(
"64bit", Is64Bit)
401 .Case(
"experimental", HasExperimental)
402 .Default(std::nullopt);
412 unsigned XLen =
getTriple().isArch64Bit() ? 64 : 32;
413 auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, Features);
416 llvm::raw_string_ostream OutputErrMsg(Buffer);
417 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
418 OutputErrMsg << ErrMsg.getMessage();
420 Diags.
Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
423 ISAInfo = std::move(*ParseResult);
429 if (
ISAInfo->hasExtension(
"zfh") ||
ISAInfo->hasExtension(
"zhinx"))
432 FastScalarUnalignedAccess =
433 llvm::is_contained(Features,
"+unaligned-scalar-mem");
435 if (llvm::is_contained(Features,
"+experimental"))
436 HasExperimental =
true;
438 if (
ABI ==
"ilp32e" &&
ISAInfo->hasExtension(
"d")) {
439 Diags.
Report(diag::err_invalid_feature_combination)
440 <<
"ILP32E cannot be used with the D ISA extension";
447 bool Is64Bit =
getTriple().isArch64Bit();
448 return llvm::RISCV::parseCPU(Name, Is64Bit);
453 bool Is64Bit =
getTriple().isArch64Bit();
454 llvm::RISCV::fillValidCPUArchList(Values, Is64Bit);
458 bool Is64Bit =
getTriple().isArch64Bit();
459 return llvm::RISCV::parseTuneCPU(Name, Is64Bit);
464 bool Is64Bit =
getTriple().isArch64Bit();
465 llvm::RISCV::fillValidTuneCPUArchList(Values, Is64Bit);
469 auto RII = llvm::RISCVISAInfo::parseArchString(
472 if (llvm::errorToBool(RII.takeError()))
473 llvm_unreachable(
"unsupport rv64i");
475 std::vector<std::string> FeatStrings =
476 (*RII)->toFeatures(
true);
477 llvm::append_range(Features, FeatStrings);
481 std::vector<std::string> &Features) {
482 auto RII = llvm::RISCVISAInfo::parseArchString(
484 if (llvm::errorToBool(RII.takeError())) {
486 Features.push_back(FullArchStr.str());
491 std::vector<std::string> FeatStrings =
492 (*RII)->toFeatures(
true);
493 llvm::append_range(Features, FeatStrings);
499 if (Features ==
"default")
502 Features.split(AttrFeatures,
";");
503 bool FoundArch =
false;
505 auto handleArchExtension = [](StringRef AttrString,
506 std::vector<std::string> &Features) {
508 AttrString.split(Exts,
",");
509 for (
auto Ext : Exts) {
513 StringRef ExtName = Ext.substr(1);
514 std::string TargetFeature =
515 llvm::RISCVISAInfo::getTargetFeatureForExtension(ExtName);
516 if (!TargetFeature.empty())
517 Features.push_back(Ext.front() + TargetFeature);
519 Features.push_back(Ext.str());
523 for (
auto &
Feature : AttrFeatures) {
525 StringRef AttrString =
Feature.split(
"=").second.trim();
527 if (
Feature.starts_with(
"arch=")) {
529 Ret.Features.clear();
531 Ret.Duplicate =
"arch=";
534 if (AttrString.starts_with(
"+")) {
536 handleArchExtension(AttrString, Ret.Features);
541 }
else if (
Feature.starts_with(
"cpu=")) {
542 if (!Ret.CPU.empty())
543 Ret.Duplicate =
"cpu=";
545 Ret.CPU = AttrString;
549 StringRef MarchFromCPU = llvm::RISCV::getMArchFromMcpu(Ret.CPU);
550 if (MarchFromCPU !=
"") {
551 Ret.Features.clear();
555 }
else if (
Feature.starts_with(
"tune=")) {
556 if (!Ret.Tune.empty())
557 Ret.Duplicate =
"tune=";
559 Ret.Tune = AttrString;
560 }
else if (
Feature.starts_with(
"priority")) {
562 }
else if (
Feature.starts_with(
"+")) {
565 handleArchExtension(
Feature, Ret.Features);
576 for (StringRef
Feature : Features) {
577 auto [LHS, RHS] =
Feature.rsplit(
';');
578 if (LHS.consume_front(
"priority="))
580 else if (RHS.consume_front(
"priority="))
585 if (!
Feature.getAsInteger(0, Priority))
586 return llvm::APInt(32, Priority);
589 return llvm::APInt::getZero(32);
618 return -1 != llvm::RISCVISAInfo::getRISCVFeaturesBitsInfo(
Feature).second;
622 return llvm::RISCVISAInfo::isSupportedExtensionFeature(Name);
626 StringRef RegName,
unsigned RegSize,
bool &HasSizeMismatch)
const {
627 if (RegName ==
"ra" || RegName ==
"sp" || RegName ==
"gp" ||
628 RegName ==
"tp" || RegName.starts_with(
"x") || RegName.starts_with(
"a") ||
629 RegName.starts_with(
"s") || RegName.starts_with(
"t")) {
630 unsigned XLen =
getTriple().isArch64Bit() ? 64 : 32;
631 HasSizeMismatch = RegSize != XLen;
639 "__builtin_cpu_is() is only supported for Linux.");
641 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)