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                     .Case("experimental", HasExperimental)
354                     .Default(std::nullopt);
355   if (Result)
356     return *Result;
357 
358   return ISAInfo->hasExtension(Feature);
359 }
360 
361 /// Perform initialization based on the user configured set of features.
362 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
363                                            DiagnosticsEngine &Diags) {
364   unsigned XLen = getTriple().isArch64Bit() ? 64 : 32;
365   auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, Features);
366   if (!ParseResult) {
367     std::string Buffer;
368     llvm::raw_string_ostream OutputErrMsg(Buffer);
369     handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
370       OutputErrMsg << ErrMsg.getMessage();
371     });
372     Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
373     return false;
374   } else {
375     ISAInfo = std::move(*ParseResult);
376   }
377 
378   if (ABI.empty())
379     ABI = ISAInfo->computeDefaultABI().str();
380 
381   if (ISAInfo->hasExtension("zfh") || ISAInfo->hasExtension("zhinx"))
382     HasLegalHalfType = true;
383 
384   FastUnalignedAccess = llvm::is_contained(Features, "+fast-unaligned-access");
385 
386   if (llvm::is_contained(Features, "+experimental"))
387     HasExperimental = true;
388 
389   return true;
390 }
391 
392 bool RISCVTargetInfo::isValidCPUName(StringRef Name) const {
393   bool Is64Bit = getTriple().isArch64Bit();
394   return llvm::RISCV::parseCPU(Name, Is64Bit);
395 }
396 
397 void RISCVTargetInfo::fillValidCPUList(
398     SmallVectorImpl<StringRef> &Values) const {
399   bool Is64Bit = getTriple().isArch64Bit();
400   llvm::RISCV::fillValidCPUArchList(Values, Is64Bit);
401 }
402 
403 bool RISCVTargetInfo::isValidTuneCPUName(StringRef Name) const {
404   bool Is64Bit = getTriple().isArch64Bit();
405   return llvm::RISCV::parseTuneCPU(Name, Is64Bit);
406 }
407 
408 void RISCVTargetInfo::fillValidTuneCPUList(
409     SmallVectorImpl<StringRef> &Values) const {
410   bool Is64Bit = getTriple().isArch64Bit();
411   llvm::RISCV::fillValidTuneCPUArchList(Values, Is64Bit);
412 }
413 
414 static void handleFullArchString(StringRef FullArchStr,
415                                  std::vector<std::string> &Features) {
416   Features.push_back("__RISCV_TargetAttrNeedOverride");
417   auto RII = llvm::RISCVISAInfo::parseArchString(
418       FullArchStr, /* EnableExperimentalExtension */ true);
419   if (!RII) {
420     consumeError(RII.takeError());
421     // Forward the invalid FullArchStr.
422     Features.push_back("+" + FullArchStr.str());
423   } else {
424     std::vector<std::string> FeatStrings = (*RII)->toFeatureVector();
425     Features.insert(Features.end(), FeatStrings.begin(), FeatStrings.end());
426   }
427 }
428 
429 ParsedTargetAttr RISCVTargetInfo::parseTargetAttr(StringRef Features) const {
430   ParsedTargetAttr Ret;
431   if (Features == "default")
432     return Ret;
433   SmallVector<StringRef, 1> AttrFeatures;
434   Features.split(AttrFeatures, ";");
435   bool FoundArch = false;
436 
437   for (auto &Feature : AttrFeatures) {
438     Feature = Feature.trim();
439     StringRef AttrString = Feature.split("=").second.trim();
440 
441     if (Feature.starts_with("arch=")) {
442       // Override last features
443       Ret.Features.clear();
444       if (FoundArch)
445         Ret.Duplicate = "arch=";
446       FoundArch = true;
447 
448       if (AttrString.starts_with("+")) {
449         // EXTENSION like arch=+v,+zbb
450         SmallVector<StringRef, 1> Exts;
451         AttrString.split(Exts, ",");
452         for (auto Ext : Exts) {
453           if (Ext.empty())
454             continue;
455 
456           StringRef ExtName = Ext.substr(1);
457           std::string TargetFeature =
458               llvm::RISCVISAInfo::getTargetFeatureForExtension(ExtName);
459           if (!TargetFeature.empty())
460             Ret.Features.push_back(Ext.front() + TargetFeature);
461           else
462             Ret.Features.push_back(Ext.str());
463         }
464       } else {
465         // full-arch-string like arch=rv64gcv
466         handleFullArchString(AttrString, Ret.Features);
467       }
468     } else if (Feature.starts_with("cpu=")) {
469       if (!Ret.CPU.empty())
470         Ret.Duplicate = "cpu=";
471 
472       Ret.CPU = AttrString;
473 
474       if (!FoundArch) {
475         // Update Features with CPU's features
476         StringRef MarchFromCPU = llvm::RISCV::getMArchFromMcpu(Ret.CPU);
477         if (MarchFromCPU != "") {
478           Ret.Features.clear();
479           handleFullArchString(MarchFromCPU, Ret.Features);
480         }
481       }
482     } else if (Feature.starts_with("tune=")) {
483       if (!Ret.Tune.empty())
484         Ret.Duplicate = "tune=";
485 
486       Ret.Tune = AttrString;
487     }
488   }
489   return Ret;
490 }
491