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