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"
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   // clang-format off
27   static const char *const GCCRegNames[] = {
28       // Integer registers
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",
33 
34       // Floating point registers
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",
39 
40       // Vector registers
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",
45 
46       // CSRs
47       "fflags", "frm", "vtype", "vl", "vxsat", "vxrm"
48     };
49   // clang-format on
50   return llvm::ArrayRef(GCCRegNames);
51 }
52 
53 ArrayRef<TargetInfo::GCCRegAlias> RISCVTargetInfo::getGCCRegAliases() const {
54   static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
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"}};
71   return llvm::ArrayRef(GCCRegAliases);
72 }
73 
74 bool RISCVTargetInfo::validateAsmConstraint(
75     const char *&Name, TargetInfo::ConstraintInfo &Info) const {
76   switch (*Name) {
77   default:
78     return false;
79   case 'I':
80     // A 12-bit signed immediate.
81     Info.setRequiresImmediate(-2048, 2047);
82     return true;
83   case 'J':
84     // Integer zero.
85     Info.setRequiresImmediate(0);
86     return true;
87   case 'K':
88     // A 5-bit unsigned immediate for CSR access instructions.
89     Info.setRequiresImmediate(0, 31);
90     return true;
91   case 'f':
92     // A floating-point register.
93     Info.setAllowsRegister();
94     return true;
95   case 'A':
96     // An address that is held in a general-purpose register.
97     Info.setAllowsMemory();
98     return true;
99   case 'S': // A symbolic address
100     Info.setAllowsRegister();
101     return true;
102   case 'v':
103     // A vector register.
104     if (Name[1] == 'r' || Name[1] == 'm') {
105       Info.setAllowsRegister();
106       Name += 1;
107       return true;
108     }
109     return false;
110   }
111 }
112 
113 std::string RISCVTargetInfo::convertConstraint(const char *&Constraint) const {
114   std::string R;
115   switch (*Constraint) {
116   case 'v':
117     R = std::string("^") + std::string(Constraint, 2);
118     Constraint += 1;
119     break;
120   default:
121     R = TargetInfo::convertConstraint(Constraint);
122     break;
123   }
124   return R;
125 }
126 
127 static unsigned getVersionValue(unsigned MajorVersion, unsigned MinorVersion) {
128   return MajorVersion * 1000000 + MinorVersion * 1000;
129 }
130 
131 void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
132                                        MacroBuilder &Builder) const {
133   Builder.defineMacro("__riscv");
134   bool Is64Bit = getTriple().isRISCV64();
135   Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32");
136   StringRef CodeModel = getTargetOpts().CodeModel;
137   unsigned FLen = ISAInfo->getFLen();
138   unsigned MinVLen = ISAInfo->getMinVLen();
139   unsigned MaxELen = ISAInfo->getMaxELen();
140   unsigned MaxELenFp = ISAInfo->getMaxELenFp();
141   if (CodeModel == "default")
142     CodeModel = "small";
143 
144   if (CodeModel == "small")
145     Builder.defineMacro("__riscv_cmodel_medlow");
146   else if (CodeModel == "medium")
147     Builder.defineMacro("__riscv_cmodel_medany");
148 
149   StringRef ABIName = getABI();
150   if (ABIName == "ilp32f" || ABIName == "lp64f")
151     Builder.defineMacro("__riscv_float_abi_single");
152   else if (ABIName == "ilp32d" || ABIName == "lp64d")
153     Builder.defineMacro("__riscv_float_abi_double");
154   else
155     Builder.defineMacro("__riscv_float_abi_soft");
156 
157   if (ABIName == "ilp32e")
158     Builder.defineMacro("__riscv_abi_rve");
159 
160   Builder.defineMacro("__riscv_arch_test");
161 
162   for (auto &Extension : ISAInfo->getExtensions()) {
163     auto ExtName = Extension.first;
164     auto ExtInfo = Extension.second;
165 
166     Builder.defineMacro(
167         Twine("__riscv_", ExtName),
168         Twine(getVersionValue(ExtInfo.MajorVersion, ExtInfo.MinorVersion)));
169   }
170 
171   if (ISAInfo->hasExtension("m") || ISAInfo->hasExtension("zmmul"))
172     Builder.defineMacro("__riscv_mul");
173 
174   if (ISAInfo->hasExtension("m")) {
175     Builder.defineMacro("__riscv_div");
176     Builder.defineMacro("__riscv_muldiv");
177   }
178 
179   if (ISAInfo->hasExtension("a")) {
180     Builder.defineMacro("__riscv_atomic");
181     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
182     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
183     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
184     if (Is64Bit)
185       Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
186   }
187 
188   if (FLen) {
189     Builder.defineMacro("__riscv_flen", Twine(FLen));
190     Builder.defineMacro("__riscv_fdiv");
191     Builder.defineMacro("__riscv_fsqrt");
192   }
193 
194   if (MinVLen) {
195     Builder.defineMacro("__riscv_v_min_vlen", Twine(MinVLen));
196     Builder.defineMacro("__riscv_v_elen", Twine(MaxELen));
197     Builder.defineMacro("__riscv_v_elen_fp", Twine(MaxELenFp));
198   }
199 
200   if (ISAInfo->hasExtension("c"))
201     Builder.defineMacro("__riscv_compressed");
202 
203   if (ISAInfo->hasExtension("zve32x")) {
204     Builder.defineMacro("__riscv_vector");
205     // Currently we support the v0.12 RISC-V V intrinsics.
206     Builder.defineMacro("__riscv_v_intrinsic", Twine(getVersionValue(0, 12)));
207   }
208 
209   auto VScale = getVScaleRange(Opts);
210   if (VScale && VScale->first && VScale->first == VScale->second)
211     Builder.defineMacro("__riscv_v_fixed_vlen",
212                         Twine(VScale->first * llvm::RISCV::RVVBitsPerBlock));
213 
214   if (FastUnalignedAccess)
215     Builder.defineMacro("__riscv_misaligned_fast");
216   else
217     Builder.defineMacro("__riscv_misaligned_avoid");
218 }
219 
220 static constexpr Builtin::Info BuiltinInfo[] = {
221 #define BUILTIN(ID, TYPE, ATTRS)                                               \
222   {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
223 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
224   {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
225 #include "clang/Basic/BuiltinsRISCVVector.def"
226 #define BUILTIN(ID, TYPE, ATTRS)                                               \
227   {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
228 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
229   {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
230 #include "clang/Basic/BuiltinsRISCV.def"
231 };
232 
233 ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const {
234   return llvm::ArrayRef(BuiltinInfo,
235                         clang::RISCV::LastTSBuiltin - Builtin::FirstTSBuiltin);
236 }
237 
238 static std::vector<std::string>
239 collectNonISAExtFeature(ArrayRef<std::string> FeaturesNeedOverride, int XLen) {
240   auto ParseResult =
241       llvm::RISCVISAInfo::parseFeatures(XLen, FeaturesNeedOverride);
242 
243   if (!ParseResult) {
244     consumeError(ParseResult.takeError());
245     return std::vector<std::string>();
246   }
247 
248   std::vector<std::string> ImpliedFeatures = (*ParseResult)->toFeatureVector();
249 
250   std::vector<std::string> NonISAExtFeatureVec;
251 
252   llvm::copy_if(FeaturesNeedOverride, std::back_inserter(NonISAExtFeatureVec),
253                 [&](const std::string &Feat) {
254                   return !llvm::is_contained(ImpliedFeatures, Feat);
255                 });
256 
257   return NonISAExtFeatureVec;
258 }
259 
260 static std::vector<std::string>
261 resolveTargetAttrOverride(const std::vector<std::string> &FeaturesVec,
262                           int XLen) {
263   auto I = llvm::find(FeaturesVec, "__RISCV_TargetAttrNeedOverride");
264   if (I == FeaturesVec.end())
265     return FeaturesVec;
266 
267   ArrayRef<std::string> FeaturesNeedOverride(&*FeaturesVec.begin(), &*I);
268   std::vector<std::string> NonISAExtFeature =
269       collectNonISAExtFeature(FeaturesNeedOverride, XLen);
270 
271   std::vector<std::string> ResolvedFeature(++I, FeaturesVec.end());
272   ResolvedFeature.insert(ResolvedFeature.end(), NonISAExtFeature.begin(),
273                          NonISAExtFeature.end());
274 
275   return ResolvedFeature;
276 }
277 
278 bool RISCVTargetInfo::initFeatureMap(
279     llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
280     const std::vector<std::string> &FeaturesVec) const {
281 
282   unsigned XLen = 32;
283 
284   if (getTriple().isRISCV64()) {
285     Features["64bit"] = true;
286     XLen = 64;
287   } else {
288     Features["32bit"] = true;
289   }
290 
291   std::vector<std::string> NewFeaturesVec =
292       resolveTargetAttrOverride(FeaturesVec, XLen);
293 
294   auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, NewFeaturesVec);
295   if (!ParseResult) {
296     std::string Buffer;
297     llvm::raw_string_ostream OutputErrMsg(Buffer);
298     handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
299       OutputErrMsg << ErrMsg.getMessage();
300     });
301     Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
302     return false;
303   }
304 
305   // RISCVISAInfo makes implications for ISA features
306   std::vector<std::string> ImpliedFeatures = (*ParseResult)->toFeatureVector();
307 
308   // parseFeatures normalizes the feature set by dropping any explicit
309   // negatives, and non-extension features.  We need to preserve the later
310   // for correctness and want to preserve the former for consistency.
311   for (auto &Feature : NewFeaturesVec) {
312      StringRef ExtName = Feature;
313      assert(ExtName.size() > 1 && (ExtName[0] == '+' || ExtName[0] == '-'));
314      ExtName = ExtName.drop_front(1); // Drop '+' or '-'
315      if (!llvm::is_contained(ImpliedFeatures, ("+" + ExtName).str()) &&
316          !llvm::is_contained(ImpliedFeatures, ("-" + ExtName).str()))
317        ImpliedFeatures.push_back(Feature);
318   }
319   return TargetInfo::initFeatureMap(Features, Diags, CPU, ImpliedFeatures);
320 }
321 
322 std::optional<std::pair<unsigned, unsigned>>
323 RISCVTargetInfo::getVScaleRange(const LangOptions &LangOpts) const {
324   // RISCV::RVVBitsPerBlock is 64.
325   unsigned VScaleMin = ISAInfo->getMinVLen() / llvm::RISCV::RVVBitsPerBlock;
326 
327   if (LangOpts.VScaleMin || LangOpts.VScaleMax) {
328     // Treat Zvl*b as a lower bound on vscale.
329     VScaleMin = std::max(VScaleMin, LangOpts.VScaleMin);
330     unsigned VScaleMax = LangOpts.VScaleMax;
331     if (VScaleMax != 0 && VScaleMax < VScaleMin)
332       VScaleMax = VScaleMin;
333     return std::pair<unsigned, unsigned>(VScaleMin ? VScaleMin : 1, VScaleMax);
334   }
335 
336   if (VScaleMin > 0) {
337     unsigned VScaleMax = ISAInfo->getMaxVLen() / llvm::RISCV::RVVBitsPerBlock;
338     return std::make_pair(VScaleMin, VScaleMax);
339   }
340 
341   return std::nullopt;
342 }
343 
344 /// Return true if has this feature, need to sync with handleTargetFeatures.
345 bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
346   bool Is64Bit = getTriple().isRISCV64();
347   auto Result = llvm::StringSwitch<std::optional<bool>>(Feature)
348                     .Case("riscv", true)
349                     .Case("riscv32", !Is64Bit)
350                     .Case("riscv64", Is64Bit)
351                     .Case("32bit", !Is64Bit)
352                     .Case("64bit", Is64Bit)
353                     .Default(std::nullopt);
354   if (Result)
355     return *Result;
356 
357   return ISAInfo->hasExtension(Feature);
358 }
359 
360 /// Perform initialization based on the user configured set of features.
361 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
362                                            DiagnosticsEngine &Diags) {
363   unsigned XLen = getTriple().isArch64Bit() ? 64 : 32;
364   auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, Features);
365   if (!ParseResult) {
366     std::string Buffer;
367     llvm::raw_string_ostream OutputErrMsg(Buffer);
368     handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
369       OutputErrMsg << ErrMsg.getMessage();
370     });
371     Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
372     return false;
373   } else {
374     ISAInfo = std::move(*ParseResult);
375   }
376 
377   if (ABI.empty())
378     ABI = ISAInfo->computeDefaultABI().str();
379 
380   if (ISAInfo->hasExtension("zfh") || ISAInfo->hasExtension("zhinx"))
381     HasLegalHalfType = true;
382 
383   FastUnalignedAccess = llvm::is_contained(Features, "+fast-unaligned-access");
384 
385   return true;
386 }
387 
388 bool RISCVTargetInfo::isValidCPUName(StringRef Name) const {
389   bool Is64Bit = getTriple().isArch64Bit();
390   return llvm::RISCV::parseCPU(Name, Is64Bit);
391 }
392 
393 void RISCVTargetInfo::fillValidCPUList(
394     SmallVectorImpl<StringRef> &Values) const {
395   bool Is64Bit = getTriple().isArch64Bit();
396   llvm::RISCV::fillValidCPUArchList(Values, Is64Bit);
397 }
398 
399 bool RISCVTargetInfo::isValidTuneCPUName(StringRef Name) const {
400   bool Is64Bit = getTriple().isArch64Bit();
401   return llvm::RISCV::parseTuneCPU(Name, Is64Bit);
402 }
403 
404 void RISCVTargetInfo::fillValidTuneCPUList(
405     SmallVectorImpl<StringRef> &Values) const {
406   bool Is64Bit = getTriple().isArch64Bit();
407   llvm::RISCV::fillValidTuneCPUArchList(Values, Is64Bit);
408 }
409 
410 static void handleFullArchString(StringRef FullArchStr,
411                                  std::vector<std::string> &Features) {
412   Features.push_back("__RISCV_TargetAttrNeedOverride");
413   auto RII = llvm::RISCVISAInfo::parseArchString(
414       FullArchStr, /* EnableExperimentalExtension */ true);
415   if (!RII) {
416     consumeError(RII.takeError());
417     // Forward the invalid FullArchStr.
418     Features.push_back("+" + FullArchStr.str());
419   } else {
420     std::vector<std::string> FeatStrings = (*RII)->toFeatureVector();
421     Features.insert(Features.end(), FeatStrings.begin(), FeatStrings.end());
422   }
423 }
424 
425 ParsedTargetAttr RISCVTargetInfo::parseTargetAttr(StringRef Features) const {
426   ParsedTargetAttr Ret;
427   if (Features == "default")
428     return Ret;
429   SmallVector<StringRef, 1> AttrFeatures;
430   Features.split(AttrFeatures, ";");
431   bool FoundArch = false;
432 
433   for (auto &Feature : AttrFeatures) {
434     Feature = Feature.trim();
435     StringRef AttrString = Feature.split("=").second.trim();
436 
437     if (Feature.starts_with("arch=")) {
438       // Override last features
439       Ret.Features.clear();
440       if (FoundArch)
441         Ret.Duplicate = "arch=";
442       FoundArch = true;
443 
444       if (AttrString.starts_with("+")) {
445         // EXTENSION like arch=+v,+zbb
446         SmallVector<StringRef, 1> Exts;
447         AttrString.split(Exts, ",");
448         for (auto Ext : Exts) {
449           if (Ext.empty())
450             continue;
451 
452           StringRef ExtName = Ext.substr(1);
453           std::string TargetFeature =
454               llvm::RISCVISAInfo::getTargetFeatureForExtension(ExtName);
455           if (!TargetFeature.empty())
456             Ret.Features.push_back(Ext.front() + TargetFeature);
457           else
458             Ret.Features.push_back(Ext.str());
459         }
460       } else {
461         // full-arch-string like arch=rv64gcv
462         handleFullArchString(AttrString, Ret.Features);
463       }
464     } else if (Feature.starts_with("cpu=")) {
465       if (!Ret.CPU.empty())
466         Ret.Duplicate = "cpu=";
467 
468       Ret.CPU = AttrString;
469 
470       if (!FoundArch) {
471         // Update Features with CPU's features
472         StringRef MarchFromCPU = llvm::RISCV::getMArchFromMcpu(Ret.CPU);
473         if (MarchFromCPU != "") {
474           Ret.Features.clear();
475           handleFullArchString(MarchFromCPU, Ret.Features);
476         }
477       }
478     } else if (Feature.starts_with("tune=")) {
479       if (!Ret.Tune.empty())
480         Ret.Duplicate = "tune=";
481 
482       Ret.Tune = AttrString;
483     }
484   }
485   return Ret;
486 }
487