clang 23.0.0git
RISCV.cpp
Go to the documentation of this file.
1//===--- RISCV.cpp - Implement RISC-V target feature support --------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements RISC-V TargetInfo objects.
10//
11//===----------------------------------------------------------------------===//
12
13#include "RISCV.h"
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"
21#include <optional>
22
23using namespace clang;
24using namespace clang::targets;
25
27 // clang-format off
28 static const char *const GCCRegNames[] = {
29 // Integer registers
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",
34
35 // Floating point registers
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",
40
41 // Vector registers
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",
46
47 // CSRs
48 "fflags", "frm", "vtype", "vl", "vxsat", "vxrm", "sf.vcix_state"
49 };
50 // clang-format on
52}
53
55 static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
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"}};
72 return llvm::ArrayRef(GCCRegAliases);
73}
74
76 const char *&Name, TargetInfo::ConstraintInfo &Info) const {
77 switch (*Name) {
78 default:
79 return false;
80 case 'I':
81 // A 12-bit signed immediate.
82 Info.setRequiresImmediate(-2048, 2047);
83 return true;
84 case 'J':
85 // Integer zero.
87 return true;
88 case 'K':
89 // A 5-bit unsigned immediate for CSR access instructions.
90 Info.setRequiresImmediate(0, 31);
91 return true;
92 case 'f':
93 // A floating-point register.
94 Info.setAllowsRegister();
95 return true;
96 case 'A':
97 // An address that is held in a general-purpose register.
98 Info.setAllowsMemory();
99 return true;
100 case 's':
101 case 'S': // A symbol or label reference with a constant offset
102 Info.setAllowsRegister();
103 return true;
104 case 'c':
105 // A RVC register - GPR or FPR
106 if (Name[1] == 'r' || Name[1] == 'R' || Name[1] == 'f') {
107 Info.setAllowsRegister();
108 Name += 1;
109 return true;
110 }
111 return false;
112 case 'R':
113 // An even-odd GPR pair
114 Info.setAllowsRegister();
115 return true;
116 case 'v':
117 // A vector register.
118 if (Name[1] == 'r' || Name[1] == 'd' || Name[1] == 'm') {
119 Info.setAllowsRegister();
120 Name += 1;
121 return true;
122 }
123 return false;
124 }
125}
126
127std::string RISCVTargetInfo::convertConstraint(const char *&Constraint) const {
128 std::string R;
129 switch (*Constraint) {
130 // c* and v* are two-letter constraints on RISC-V.
131 case 'c':
132 case 'v':
133 R = std::string("^") + std::string(Constraint, 2);
134 Constraint += 1;
135 break;
136 default:
137 R = TargetInfo::convertConstraint(Constraint);
138 break;
139 }
140 return R;
141}
142
143static unsigned getVersionValue(unsigned MajorVersion, unsigned MinorVersion) {
144 return MajorVersion * 1000000 + MinorVersion * 1000;
145}
146
148 MacroBuilder &Builder) const {
149 Builder.defineMacro("__riscv");
150 bool Is64Bit = getTriple().isRISCV64();
151 Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32");
152 StringRef CodeModel = getTargetOpts().CodeModel;
153 unsigned FLen = ISAInfo->getFLen();
154 unsigned MinVLen = ISAInfo->getMinVLen();
155 unsigned MaxELen = ISAInfo->getMaxELen();
156 unsigned MaxELenFp = ISAInfo->getMaxELenFp();
157 if (CodeModel == "default")
158 CodeModel = "small";
159
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");
166
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");
172 else
173 Builder.defineMacro("__riscv_float_abi_soft");
174
175 if (ABIName == "ilp32e" || ABIName == "lp64e")
176 Builder.defineMacro("__riscv_abi_rve");
177
178 Builder.defineMacro("__riscv_arch_test");
179
180 for (auto &Extension : ISAInfo->getExtensions()) {
181 auto ExtName = Extension.first;
182 auto ExtInfo = Extension.second;
183
184 Builder.defineMacro(Twine("__riscv_", ExtName),
185 Twine(getVersionValue(ExtInfo.Major, ExtInfo.Minor)));
186 }
187
188 if (ISAInfo->hasExtension("zmmul"))
189 Builder.defineMacro("__riscv_mul");
190
191 if (ISAInfo->hasExtension("m")) {
192 Builder.defineMacro("__riscv_div");
193 Builder.defineMacro("__riscv_muldiv");
194 }
195
196 // The "a" extension is composed of "zalrsc" and "zaamo"
197 if (ISAInfo->hasExtension("a"))
198 Builder.defineMacro("__riscv_atomic");
199
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");
204 if (Is64Bit)
205 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
206 }
207
208 if (FLen) {
209 Builder.defineMacro("__riscv_flen", Twine(FLen));
210 Builder.defineMacro("__riscv_fdiv");
211 Builder.defineMacro("__riscv_fsqrt");
212 }
213
214 if (MinVLen) {
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));
218 }
219
220 if (ISAInfo->hasExtension("c"))
221 Builder.defineMacro("__riscv_compressed");
222
223 if (ISAInfo->hasExtension("zve32x"))
224 Builder.defineMacro("__riscv_vector");
225
226 // Currently we support the v1.0 RISC-V V intrinsics.
227 Builder.defineMacro("__riscv_v_intrinsic", Twine(getVersionValue(1, 0)));
228
230 if (VScale && VScale->first && VScale->first == VScale->second)
231 Builder.defineMacro("__riscv_v_fixed_vlen",
232 Twine(VScale->first * llvm::RISCV::RVVBitsPerBlock));
233
234 if (FastScalarUnalignedAccess)
235 Builder.defineMacro("__riscv_misaligned_fast");
236 else
237 Builder.defineMacro("__riscv_misaligned_avoid");
238
239 if (ISAInfo->hasExtension("e")) {
240 if (Is64Bit)
241 Builder.defineMacro("__riscv_64e");
242 else
243 Builder.defineMacro("__riscv_32e");
244 }
245
246 if (Opts.CFProtectionReturn && ISAInfo->hasExtension("zicfiss"))
247 Builder.defineMacro("__riscv_shadow_stack");
248
249 if (Opts.CFProtectionBranch) {
250 auto Scheme = Opts.getCFBranchLabelScheme();
253
254 Builder.defineMacro("__riscv_landing_pad");
255 switch (Scheme) {
256 case CFBranchLabelSchemeKind::Unlabeled:
257 Builder.defineMacro("__riscv_landing_pad_unlabeled");
258 break;
259 case CFBranchLabelSchemeKind::FuncSig:
260 // TODO: Define macros after the func-sig scheme is implemented
261 break;
263 llvm_unreachable("default cf-branch-label scheme should already be "
264 "transformed to other scheme");
265 }
266 }
267}
268
269static constexpr int NumRVVBuiltins =
271static constexpr int NumRVVSiFiveBuiltins =
273static constexpr int NumRVVAndesBuiltins =
275static constexpr int NumRISCVBuiltins =
277static constexpr int NumBuiltins =
281
282namespace RVV {
283#define GET_RISCVV_BUILTIN_STR_TABLE
284#include "clang/Basic/riscv_vector_builtins.inc"
285#undef GET_RISCVV_BUILTIN_STR_TABLE
286static_assert(BuiltinStrings.size() < 100'000);
287
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
292};
293} // namespace RVV
294
295namespace RVVSiFive {
296#define GET_RISCVV_BUILTIN_STR_TABLE
297#include "clang/Basic/riscv_sifive_vector_builtins.inc"
298#undef GET_RISCVV_BUILTIN_STR_TABLE
299
300static constexpr std::array<Builtin::Info, NumRVVSiFiveBuiltins> BuiltinInfos =
301 {
302#define GET_RISCVV_BUILTIN_INFOS
303#include "clang/Basic/riscv_sifive_vector_builtins.inc"
304#undef GET_RISCVV_BUILTIN_INFOS
305};
306} // namespace RVVSiFive
307
308namespace RVVAndes {
309#define GET_RISCVV_BUILTIN_STR_TABLE
310#include "clang/Basic/riscv_andes_vector_builtins.inc"
311#undef GET_RISCVV_BUILTIN_STR_TABLE
312
313static constexpr std::array<Builtin::Info, NumRVVAndesBuiltins> BuiltinInfos =
314 {
315#define GET_RISCVV_BUILTIN_INFOS
316#include "clang/Basic/riscv_andes_vector_builtins.inc"
317#undef GET_RISCVV_BUILTIN_INFOS
318};
319} // namespace RVVAndes
320
321#define GET_BUILTIN_STR_TABLE
322#include "clang/Basic/BuiltinsRISCV.inc"
323#undef GET_BUILTIN_STR_TABLE
324
325static constexpr Builtin::Info BuiltinInfos[] = {
326#define GET_BUILTIN_INFOS
327#include "clang/Basic/BuiltinsRISCV.inc"
328#undef GET_BUILTIN_INFOS
329};
330static_assert(std::size(BuiltinInfos) == NumRISCVBuiltins);
331
332llvm::SmallVector<Builtin::InfosShard>
334 return {
335 {&RVV::BuiltinStrings, RVV::BuiltinInfos, "__builtin_rvv_"},
336 {&RVVSiFive::BuiltinStrings, RVVSiFive::BuiltinInfos, "__builtin_rvv_"},
337 {&RVVAndes::BuiltinStrings, RVVAndes::BuiltinInfos, "__builtin_rvv_"},
339 };
340}
341
343 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
344 const std::vector<std::string> &FeaturesVec) const {
345
346 unsigned XLen = 32;
347
348 if (getTriple().isRISCV64()) {
349 Features["64bit"] = true;
350 XLen = 64;
351 } else {
352 Features["32bit"] = true;
353 }
354
355 std::vector<std::string> AllFeatures = FeaturesVec;
356 auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, FeaturesVec);
357 if (!ParseResult) {
358 std::string Buffer;
359 llvm::raw_string_ostream OutputErrMsg(Buffer);
360 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
361 OutputErrMsg << ErrMsg.getMessage();
362 });
363 Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
364 return false;
365 }
366
367 // Append all features, not just new ones, so we override any negatives.
368 llvm::append_range(AllFeatures, (*ParseResult)->toFeatures());
369 return TargetInfo::initFeatureMap(Features, Diags, CPU, AllFeatures);
370}
371
372std::optional<std::pair<unsigned, unsigned>>
375 llvm::StringMap<bool> *FeatureMap) const {
376 // RISCV::RVVBitsPerBlock is 64.
377 unsigned VScaleMin = ISAInfo->getMinVLen() / llvm::RISCV::RVVBitsPerBlock;
378
379 if (LangOpts.VScaleMin || LangOpts.VScaleMax) {
380 // Treat Zvl*b as a lower bound on vscale.
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);
386 }
387
388 if (VScaleMin > 0) {
389 unsigned VScaleMax = ISAInfo->getMaxVLen() / llvm::RISCV::RVVBitsPerBlock;
390 return std::make_pair(VScaleMin, VScaleMax);
391 }
392
393 return std::nullopt;
394}
395
396/// Return true if has this feature, need to sync with handleTargetFeatures.
398 bool Is64Bit = getTriple().isRISCV64();
399 auto Result = llvm::StringSwitch<std::optional<bool>>(Feature)
400 .Case("riscv", true)
401 .Case("riscv32", !Is64Bit)
402 .Case("riscv64", Is64Bit)
403 .Case("32bit", !Is64Bit)
404 .Case("64bit", Is64Bit)
405 .Case("experimental", HasExperimental)
406 .Default(std::nullopt);
407 if (Result)
408 return *Result;
409
410 return ISAInfo->hasExtension(Feature);
411}
412
413/// Perform initialization based on the user configured set of features.
414bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
415 DiagnosticsEngine &Diags) {
416 unsigned XLen = getTriple().isArch64Bit() ? 64 : 32;
417 auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, Features);
418 if (!ParseResult) {
419 std::string Buffer;
420 llvm::raw_string_ostream OutputErrMsg(Buffer);
421 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
422 OutputErrMsg << ErrMsg.getMessage();
423 });
424 Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
425 return false;
426 } else {
427 ISAInfo = std::move(*ParseResult);
428 }
429
430 if (ABI.empty())
431 ABI = ISAInfo->computeDefaultABI().str();
432
433 if (ISAInfo->hasExtension("zfh") || ISAInfo->hasExtension("zhinx"))
434 HasFastHalfType = true;
435
436 FastScalarUnalignedAccess =
437 llvm::is_contained(Features, "+unaligned-scalar-mem");
438
439 if (llvm::is_contained(Features, "+experimental"))
440 HasExperimental = true;
441
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";
445 return false;
446 }
447 return true;
448}
449
450bool RISCVTargetInfo::isValidCPUName(StringRef Name) const {
451 bool Is64Bit = getTriple().isArch64Bit();
452 return llvm::RISCV::parseCPU(Name, Is64Bit);
453}
454
456 SmallVectorImpl<StringRef> &Values) const {
457 bool Is64Bit = getTriple().isArch64Bit();
458 llvm::RISCV::fillValidCPUArchList(Values, Is64Bit);
459}
460
461bool RISCVTargetInfo::isValidTuneCPUName(StringRef Name) const {
462 bool Is64Bit = getTriple().isArch64Bit();
463 return llvm::RISCV::parseTuneCPU(Name, Is64Bit);
464}
465
467 SmallVectorImpl<StringRef> &Values) const {
468 bool Is64Bit = getTriple().isArch64Bit();
469 llvm::RISCV::fillValidTuneCPUArchList(Values, Is64Bit);
470}
471
472static void populateNegativeRISCVFeatures(std::vector<std::string> &Features) {
473 auto RII = llvm::RISCVISAInfo::parseArchString(
474 "rv64i", /* EnableExperimentalExtension */ true);
475
476 if (llvm::errorToBool(RII.takeError()))
477 llvm_unreachable("unsupport rv64i");
478
479 std::vector<std::string> FeatStrings =
480 (*RII)->toFeatures(/* AddAllExtensions */ true);
481 llvm::append_range(Features, FeatStrings);
482}
483
484static void handleFullArchString(StringRef FullArchStr,
485 std::vector<std::string> &Features) {
486 auto RII = llvm::RISCVISAInfo::parseArchString(
487 FullArchStr, /* EnableExperimentalExtension */ true);
488 if (llvm::errorToBool(RII.takeError())) {
489 // Forward the invalid FullArchStr.
490 Features.push_back(FullArchStr.str());
491 } else {
492 // Append a full list of features, including any negative extensions so that
493 // we override the CPU's features.
495 std::vector<std::string> FeatStrings =
496 (*RII)->toFeatures(/* AddAllExtensions */ true);
497 llvm::append_range(Features, FeatStrings);
498 }
499}
500
503 if (Features == "default")
504 return Ret;
505 SmallVector<StringRef, 1> AttrFeatures;
506 Features.split(AttrFeatures, ";");
507 bool FoundArch = false;
508
509 auto handleArchExtension = [](StringRef AttrString,
510 std::vector<std::string> &Features) {
512 AttrString.split(Exts, ",");
513 for (auto Ext : Exts) {
514 if (Ext.empty())
515 continue;
516
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);
522 else
523 Features.push_back(Ext.str());
524 }
525 };
526
527 for (auto &Feature : AttrFeatures) {
528 Feature = Feature.trim();
529 StringRef AttrString = Feature.split("=").second.trim();
530
531 if (Feature.starts_with("arch=")) {
532 // Override last features
533 Ret.Features.clear();
534 if (FoundArch)
535 Ret.Duplicate = "arch=";
536 FoundArch = true;
537
538 if (AttrString.starts_with("+")) {
539 // EXTENSION like arch=+v,+zbb
540 handleArchExtension(AttrString, Ret.Features);
541 } else {
542 // full-arch-string like arch=rv64gcv
543 handleFullArchString(AttrString, Ret.Features);
544 }
545 } else if (Feature.starts_with("cpu=")) {
546 if (!Ret.CPU.empty())
547 Ret.Duplicate = "cpu=";
548
549 Ret.CPU = AttrString;
550
551 if (!FoundArch) {
552 // Update Features with CPU's features
553 StringRef MarchFromCPU = llvm::RISCV::getMArchFromMcpu(Ret.CPU);
554 if (MarchFromCPU != "") {
555 Ret.Features.clear();
556 handleFullArchString(MarchFromCPU, Ret.Features);
557 }
558 }
559 } else if (Feature.starts_with("tune=")) {
560 if (!Ret.Tune.empty())
561 Ret.Duplicate = "tune=";
562
563 Ret.Tune = AttrString;
564 } else if (Feature.starts_with("priority")) {
565 // Skip because it only use for FMV.
566 } else if (Feature.starts_with("+")) {
567 // Handle target_version/target_clones attribute strings
568 // that are already delimited by ','
569 handleArchExtension(Feature, Ret.Features);
570 }
571 }
572 return Ret;
573}
574
575llvm::APInt
577 // Priority is explicitly specified on RISC-V unlike on other targets, where
578 // it is derived by all the features of a specific version. Therefore if a
579 // feature contains the priority string, then return it immediately.
580 for (StringRef Feature : Features) {
581 auto [LHS, RHS] = Feature.rsplit(';');
582 if (LHS.consume_front("priority="))
583 Feature = LHS;
584 else if (RHS.consume_front("priority="))
585 Feature = RHS;
586 else
587 continue;
588 unsigned Priority;
589 if (!Feature.getAsInteger(0, Priority))
590 return llvm::APInt(32, Priority);
591 }
592 // Default Priority is zero.
593 return llvm::APInt::getZero(32);
594}
595
598 switch (CC) {
599 default:
600 return CCCR_Warning;
601 case CC_C:
615 return CCCR_OK;
616 }
617}
618
620 // Only allow extensions we have a known bit position for in the
621 // __riscv_feature_bits structure.
622 return -1 != llvm::RISCVISAInfo::getRISCVFeaturesBitsInfo(Feature).second;
623}
624
625bool RISCVTargetInfo::isValidFeatureName(StringRef Name) const {
626 return llvm::RISCVISAInfo::isSupportedExtensionFeature(Name);
627}
628
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;
636 return true;
637 }
638 return false;
639}
640
641bool RISCVTargetInfo::validateCpuIs(StringRef CPUName) const {
642 assert(getTriple().isOSLinux() &&
643 "__builtin_cpu_is() is only supported for Linux.");
644
645 return llvm::RISCV::hasValidCPUModel(CPUName);
646}
647
649 const CFBranchLabelSchemeKind Scheme, DiagnosticsEngine &Diags) const {
650 // TODO: Allow the default func-sig scheme to be selected after backend
651 // implements it
652 switch (Scheme) {
654 Diags.Report(diag::err_opt_not_valid_without_opt)
655 << "-fcf-protection=branch"
656 << (Twine("-mcf-branch-label-scheme=") +
657 getCFBranchLabelSchemeFlagVal(CFBranchLabelSchemeKind::Unlabeled))
658 .str();
659 return false;
660 case CFBranchLabelSchemeKind::Unlabeled:
661 return true;
662 case CFBranchLabelSchemeKind::FuncSig:
663 Diags.Report(diag::err_opt_unsupported_with_suggest)
664 << (Twine("-mcf-branch-label-scheme=") +
665 getCFBranchLabelSchemeFlagVal(CFBranchLabelSchemeKind::FuncSig))
666 .str()
667 << (Twine("-mcf-branch-label-scheme=") +
668 getCFBranchLabelSchemeFlagVal(CFBranchLabelSchemeKind::Unlabeled))
669 .str();
670 return false;
671 }
673}
Defines the Diagnostic-related interfaces.
static constexpr llvm::StringTable BuiltinStrings
Definition ARM.cpp:1115
static constexpr int NumRISCVBuiltins
Definition RISCV.cpp:275
static constexpr int NumRVVAndesBuiltins
Definition RISCV.cpp:273
static constexpr int NumRVVBuiltins
Definition RISCV.cpp:269
static void populateNegativeRISCVFeatures(std::vector< std::string > &Features)
Definition RISCV.cpp:472
static constexpr int NumRVVSiFiveBuiltins
Definition RISCV.cpp:271
static unsigned getVersionValue(unsigned MajorVersion, unsigned MinorVersion)
Definition RISCV.cpp:143
static void handleFullArchString(StringRef FullArchStr, std::vector< std::string > &Features)
Definition RISCV.cpp:484
static constexpr Builtin::Info BuiltinInfos[]
Definition Builtins.cpp:39
static constexpr unsigned NumBuiltins
Definition Builtins.cpp:33
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.
Definition Diagnostic.h:234
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.
Definition TargetInfo.h:330
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.
Definition RISCV.cpp:625
std::string convertConstraint(const char *&Constraint) const override
Definition RISCV.cpp:127
void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override
===-— Other target property query methods -----------------------—===//
Definition RISCV.cpp:147
bool validateAsmConstraint(const char *&Name, TargetInfo::ConstraintInfo &Info) const override
Definition RISCV.cpp:75
bool validateGlobalRegisterVariable(StringRef RegName, unsigned RegSize, bool &HasSizeMismatch) const override
Validate register name used for global register variables.
Definition RISCV.cpp:629
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 ...
Definition RISCV.cpp:342
std::unique_ptr< llvm::RISCVISAInfo > ISAInfo
Definition RISCV.h:30
void fillValidTuneCPUList(SmallVectorImpl< StringRef > &Values) const override
Fill a SmallVectorImpl with the valid values for tuning CPU.
Definition RISCV.cpp:466
bool isValidTuneCPUName(StringRef Name) const override
Determine whether this TargetInfo supports the given CPU name for tuning.
Definition RISCV.cpp:461
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override
Determines whether a given calling convention is valid for the target.
Definition RISCV.cpp:597
ArrayRef< const char * > getGCCRegNames() const override
Definition RISCV.cpp:26
ArrayRef< TargetInfo::GCCRegAlias > getGCCRegAliases() const override
Definition RISCV.cpp:54
void fillValidCPUList(SmallVectorImpl< StringRef > &Values) const override
Fill a SmallVectorImpl with the valid values to setCPU.
Definition RISCV.cpp:455
llvm::APInt getFMVPriority(ArrayRef< StringRef > Features) const override
Definition RISCV.cpp:576
bool validateCpuSupports(StringRef Feature) const override
Definition RISCV.cpp:619
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.
Definition RISCV.cpp:373
StringRef getABI() const override
Get the ABI currently in use.
Definition RISCV.h:61
bool checkCFBranchLabelSchemeSupported(const CFBranchLabelSchemeKind Scheme, DiagnosticsEngine &Diags) const override
Definition RISCV.cpp:648
CFBranchLabelSchemeKind getDefaultCFBranchLabelScheme() const override
Get the target default CFBranchLabelScheme scheme.
Definition RISCV.h:155
bool handleTargetFeatures(std::vector< std::string > &Features, DiagnosticsEngine &Diags) override
Perform initialization based on the user configured set of features.
Definition RISCV.cpp:414
llvm::SmallVector< Builtin::InfosShard > getTargetBuiltins() const override
Return information about target-specific builtins for the current primary target, and info about whic...
Definition RISCV.cpp:333
ParsedTargetAttr parseTargetAttr(StringRef Str) const override
Definition RISCV.cpp:501
bool hasFeature(StringRef Feature) const override
Return true if has this feature, need to sync with handleTargetFeatures.
Definition RISCV.cpp:397
bool validateCpuIs(StringRef CPUName) const override
Definition RISCV.cpp:641
bool isValidCPUName(StringRef Name) const override
Determine whether this TargetInfo supports the given CPU name.
Definition RISCV.cpp:450
static constexpr std::array< Builtin::Info, NumRVVAndesBuiltins > BuiltinInfos
Definition RISCV.cpp:313
static constexpr std::array< Builtin::Info, NumRVVSiFiveBuiltins > BuiltinInfos
Definition RISCV.cpp:300
Definition RISCV.cpp:282
static constexpr std::array< Builtin::Info, NumRVVBuiltins > BuiltinInfos
Definition RISCV.cpp:288
static const char *const GCCRegNames[]
Definition X86.cpp:73
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
Definition TypeBase.h:905
static const char * getCFBranchLabelSchemeFlagVal(const CFBranchLabelSchemeKind Scheme)
CallingConv
CallingConv - Specifies the calling convention that a function uses.
Definition Specifiers.h:279
@ CC_RISCVVLSCall_64
Definition Specifiers.h:304
@ CC_RISCVVLSCall_128
Definition Specifiers.h:305
@ CC_RISCVVLSCall_65536
Definition Specifiers.h:315
@ CC_RISCVVLSCall_4096
Definition Specifiers.h:311
@ CC_RISCVVLSCall_8192
Definition Specifiers.h:312
@ CC_RISCVVLSCall_512
Definition Specifiers.h:308
@ CC_RISCVVectorCall
Definition Specifiers.h:302
@ CC_RISCVVLSCall_32
Definition Specifiers.h:303
@ CC_RISCVVLSCall_16384
Definition Specifiers.h:313
@ CC_RISCVVLSCall_2048
Definition Specifiers.h:310
@ CC_RISCVVLSCall_256
Definition Specifiers.h:307
@ CC_RISCVVLSCall_1024
Definition Specifiers.h:309
@ CC_RISCVVLSCall_32768
Definition Specifiers.h:314
bool IsArmStreamingFunction(const FunctionDecl *FD, bool IncludeLocallyStreaming)
Returns whether the given FunctionDecl has an __arm[_locally]_streaming attribute.
Definition Decl.cpp:6102
The info used to represent each builtin.
Definition Builtins.h:80
Contains information gathered from parsing the contents of TargetAttr.
Definition TargetInfo.h:60
void setRequiresImmediate(int Min, int Max)