[docs] Fix build-docs.sh
[llvm-project.git] / clang / lib / Basic / Targets / RISCV.cpp
blobcb0d10abc7e358d46cd39094b83a6fb6537fb5a2
1 //===--- RISCV.cpp - Implement RISCV 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 RISCV TargetInfo objects.
11 //===----------------------------------------------------------------------===//
13 #include "RISCV.h"
14 #include "clang/Basic/Diagnostic.h"
15 #include "clang/Basic/MacroBuilder.h"
16 #include "clang/Basic/TargetBuiltins.h"
17 #include "llvm/ADT/StringSwitch.h"
18 #include "llvm/Support/TargetParser.h"
19 #include "llvm/Support/raw_ostream.h"
21 using namespace clang;
22 using namespace clang::targets;
24 ArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const {
25 static const char *const GCCRegNames[] = {
26 // Integer registers
27 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
28 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
29 "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
30 "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31",
32 // Floating point registers
33 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
34 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
35 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
36 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
38 // Vector registers
39 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
40 "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
41 "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
42 "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"};
43 return llvm::makeArrayRef(GCCRegNames);
46 ArrayRef<TargetInfo::GCCRegAlias> RISCVTargetInfo::getGCCRegAliases() const {
47 static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
48 {{"zero"}, "x0"}, {{"ra"}, "x1"}, {{"sp"}, "x2"}, {{"gp"}, "x3"},
49 {{"tp"}, "x4"}, {{"t0"}, "x5"}, {{"t1"}, "x6"}, {{"t2"}, "x7"},
50 {{"s0"}, "x8"}, {{"s1"}, "x9"}, {{"a0"}, "x10"}, {{"a1"}, "x11"},
51 {{"a2"}, "x12"}, {{"a3"}, "x13"}, {{"a4"}, "x14"}, {{"a5"}, "x15"},
52 {{"a6"}, "x16"}, {{"a7"}, "x17"}, {{"s2"}, "x18"}, {{"s3"}, "x19"},
53 {{"s4"}, "x20"}, {{"s5"}, "x21"}, {{"s6"}, "x22"}, {{"s7"}, "x23"},
54 {{"s8"}, "x24"}, {{"s9"}, "x25"}, {{"s10"}, "x26"}, {{"s11"}, "x27"},
55 {{"t3"}, "x28"}, {{"t4"}, "x29"}, {{"t5"}, "x30"}, {{"t6"}, "x31"},
56 {{"ft0"}, "f0"}, {{"ft1"}, "f1"}, {{"ft2"}, "f2"}, {{"ft3"}, "f3"},
57 {{"ft4"}, "f4"}, {{"ft5"}, "f5"}, {{"ft6"}, "f6"}, {{"ft7"}, "f7"},
58 {{"fs0"}, "f8"}, {{"fs1"}, "f9"}, {{"fa0"}, "f10"}, {{"fa1"}, "f11"},
59 {{"fa2"}, "f12"}, {{"fa3"}, "f13"}, {{"fa4"}, "f14"}, {{"fa5"}, "f15"},
60 {{"fa6"}, "f16"}, {{"fa7"}, "f17"}, {{"fs2"}, "f18"}, {{"fs3"}, "f19"},
61 {{"fs4"}, "f20"}, {{"fs5"}, "f21"}, {{"fs6"}, "f22"}, {{"fs7"}, "f23"},
62 {{"fs8"}, "f24"}, {{"fs9"}, "f25"}, {{"fs10"}, "f26"}, {{"fs11"}, "f27"},
63 {{"ft8"}, "f28"}, {{"ft9"}, "f29"}, {{"ft10"}, "f30"}, {{"ft11"}, "f31"}};
64 return llvm::makeArrayRef(GCCRegAliases);
67 bool RISCVTargetInfo::validateAsmConstraint(
68 const char *&Name, TargetInfo::ConstraintInfo &Info) const {
69 switch (*Name) {
70 default:
71 return false;
72 case 'I':
73 // A 12-bit signed immediate.
74 Info.setRequiresImmediate(-2048, 2047);
75 return true;
76 case 'J':
77 // Integer zero.
78 Info.setRequiresImmediate(0);
79 return true;
80 case 'K':
81 // A 5-bit unsigned immediate for CSR access instructions.
82 Info.setRequiresImmediate(0, 31);
83 return true;
84 case 'f':
85 // A floating-point register.
86 Info.setAllowsRegister();
87 return true;
88 case 'A':
89 // An address that is held in a general-purpose register.
90 Info.setAllowsMemory();
91 return true;
92 case 'S': // A symbolic address
93 Info.setAllowsRegister();
94 return true;
95 case 'v':
96 // A vector register.
97 if (Name[1] == 'r' || Name[1] == 'm') {
98 Info.setAllowsRegister();
99 Name += 1;
100 return true;
102 return false;
106 std::string RISCVTargetInfo::convertConstraint(const char *&Constraint) const {
107 std::string R;
108 switch (*Constraint) {
109 case 'v':
110 R = std::string("^") + std::string(Constraint, 2);
111 Constraint += 1;
112 break;
113 default:
114 R = TargetInfo::convertConstraint(Constraint);
115 break;
117 return R;
120 void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
121 MacroBuilder &Builder) const {
122 Builder.defineMacro("__ELF__");
123 Builder.defineMacro("__riscv");
124 bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
125 Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32");
126 StringRef CodeModel = getTargetOpts().CodeModel;
127 unsigned FLen = ISAInfo->getFLen();
128 unsigned MinVLen = ISAInfo->getMinVLen();
129 unsigned MaxELen = ISAInfo->getMaxELen();
130 unsigned MaxELenFp = ISAInfo->getMaxELenFp();
131 if (CodeModel == "default")
132 CodeModel = "small";
134 if (CodeModel == "small")
135 Builder.defineMacro("__riscv_cmodel_medlow");
136 else if (CodeModel == "medium")
137 Builder.defineMacro("__riscv_cmodel_medany");
139 StringRef ABIName = getABI();
140 if (ABIName == "ilp32f" || ABIName == "lp64f")
141 Builder.defineMacro("__riscv_float_abi_single");
142 else if (ABIName == "ilp32d" || ABIName == "lp64d")
143 Builder.defineMacro("__riscv_float_abi_double");
144 else
145 Builder.defineMacro("__riscv_float_abi_soft");
147 if (ABIName == "ilp32e")
148 Builder.defineMacro("__riscv_abi_rve");
150 Builder.defineMacro("__riscv_arch_test");
152 for (auto &Extension : ISAInfo->getExtensions()) {
153 auto ExtName = Extension.first;
154 auto ExtInfo = Extension.second;
155 unsigned Version =
156 (ExtInfo.MajorVersion * 1000000) + (ExtInfo.MinorVersion * 1000);
158 Builder.defineMacro(Twine("__riscv_", ExtName), Twine(Version));
161 if (ISAInfo->hasExtension("m") || ISAInfo->hasExtension("zmmul"))
162 Builder.defineMacro("__riscv_mul");
164 if (ISAInfo->hasExtension("m")) {
165 Builder.defineMacro("__riscv_div");
166 Builder.defineMacro("__riscv_muldiv");
169 if (ISAInfo->hasExtension("a")) {
170 Builder.defineMacro("__riscv_atomic");
171 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
172 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
173 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
174 if (Is64Bit)
175 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
178 if (FLen) {
179 Builder.defineMacro("__riscv_flen", Twine(FLen));
180 Builder.defineMacro("__riscv_fdiv");
181 Builder.defineMacro("__riscv_fsqrt");
184 if (MinVLen) {
185 Builder.defineMacro("__riscv_v_min_vlen", Twine(MinVLen));
186 Builder.defineMacro("__riscv_v_elen", Twine(MaxELen));
187 Builder.defineMacro("__riscv_v_elen_fp", Twine(MaxELenFp));
190 if (ISAInfo->hasExtension("c"))
191 Builder.defineMacro("__riscv_compressed");
193 if (ISAInfo->hasExtension("zve32x"))
194 Builder.defineMacro("__riscv_vector");
197 const Builtin::Info RISCVTargetInfo::BuiltinInfo[] = {
198 #define BUILTIN(ID, TYPE, ATTRS) \
199 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
200 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
201 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
202 #include "clang/Basic/BuiltinsRISCVVector.def"
203 #define BUILTIN(ID, TYPE, ATTRS) \
204 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
205 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
206 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
207 #include "clang/Basic/BuiltinsRISCV.def"
210 ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const {
211 return llvm::makeArrayRef(BuiltinInfo, clang::RISCV::LastTSBuiltin -
212 Builtin::FirstTSBuiltin);
215 bool RISCVTargetInfo::initFeatureMap(
216 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
217 const std::vector<std::string> &FeaturesVec) const {
219 unsigned XLen = 32;
221 if (getTriple().getArch() == llvm::Triple::riscv64) {
222 Features["64bit"] = true;
223 XLen = 64;
224 } else {
225 Features["32bit"] = true;
228 auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, FeaturesVec);
229 if (!ParseResult) {
230 std::string Buffer;
231 llvm::raw_string_ostream OutputErrMsg(Buffer);
232 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
233 OutputErrMsg << ErrMsg.getMessage();
235 Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
236 return false;
239 // RISCVISAInfo makes implications for ISA features
240 std::vector<std::string> ImpliedFeatures = (*ParseResult)->toFeatureVector();
241 // Add non-ISA features like `relax` and `save-restore` back
242 for (const std::string &Feature : FeaturesVec)
243 if (!llvm::is_contained(ImpliedFeatures, Feature))
244 ImpliedFeatures.push_back(Feature);
246 return TargetInfo::initFeatureMap(Features, Diags, CPU, ImpliedFeatures);
249 /// Return true if has this feature, need to sync with handleTargetFeatures.
250 bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
251 bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
252 auto Result = llvm::StringSwitch<Optional<bool>>(Feature)
253 .Case("riscv", true)
254 .Case("riscv32", !Is64Bit)
255 .Case("riscv64", Is64Bit)
256 .Case("32bit", !Is64Bit)
257 .Case("64bit", Is64Bit)
258 .Default(None);
259 if (Result)
260 return Result.value();
262 if (ISAInfo->isSupportedExtensionFeature(Feature))
263 return ISAInfo->hasExtension(Feature);
265 return false;
268 /// Perform initialization based on the user configured set of features.
269 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
270 DiagnosticsEngine &Diags) {
271 unsigned XLen = getTriple().isArch64Bit() ? 64 : 32;
272 auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, Features);
273 if (!ParseResult) {
274 std::string Buffer;
275 llvm::raw_string_ostream OutputErrMsg(Buffer);
276 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
277 OutputErrMsg << ErrMsg.getMessage();
279 Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
280 return false;
281 } else {
282 ISAInfo = std::move(*ParseResult);
285 if (ABI.empty())
286 ABI = ISAInfo->computeDefaultABI().str();
288 return true;
291 bool RISCVTargetInfo::isValidCPUName(StringRef Name) const {
292 bool Is64Bit = getTriple().isArch64Bit();
293 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), Is64Bit);
296 void RISCVTargetInfo::fillValidCPUList(
297 SmallVectorImpl<StringRef> &Values) const {
298 bool Is64Bit = getTriple().isArch64Bit();
299 llvm::RISCV::fillValidCPUArchList(Values, Is64Bit);
302 bool RISCVTargetInfo::isValidTuneCPUName(StringRef Name) const {
303 bool Is64Bit = getTriple().isArch64Bit();
304 return llvm::RISCV::checkTuneCPUKind(
305 llvm::RISCV::parseTuneCPUKind(Name, Is64Bit), Is64Bit);
308 void RISCVTargetInfo::fillValidTuneCPUList(
309 SmallVectorImpl<StringRef> &Values) const {
310 bool Is64Bit = getTriple().isArch64Bit();
311 llvm::RISCV::fillValidTuneCPUArchList(Values, Is64Bit);