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/TargetParser.h"
19 #include "llvm/Support/raw_ostream.h"
20 
21 using namespace clang;
22 using namespace clang::targets;
23 
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",
31 
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",
37 
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);
44 }
45 
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);
65 }
66 
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;
101     }
102     return false;
103   }
104 }
105 
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;
116   }
117   return R;
118 }
119 
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   if (CodeModel == "default")
130     CodeModel = "small";
131 
132   if (CodeModel == "small")
133     Builder.defineMacro("__riscv_cmodel_medlow");
134   else if (CodeModel == "medium")
135     Builder.defineMacro("__riscv_cmodel_medany");
136 
137   StringRef ABIName = getABI();
138   if (ABIName == "ilp32f" || ABIName == "lp64f")
139     Builder.defineMacro("__riscv_float_abi_single");
140   else if (ABIName == "ilp32d" || ABIName == "lp64d")
141     Builder.defineMacro("__riscv_float_abi_double");
142   else
143     Builder.defineMacro("__riscv_float_abi_soft");
144 
145   if (ABIName == "ilp32e")
146     Builder.defineMacro("__riscv_abi_rve");
147 
148   Builder.defineMacro("__riscv_arch_test");
149 
150   for (auto &Extension : ISAInfo->getExtensions()) {
151     auto ExtName = Extension.first;
152     auto ExtInfo = Extension.second;
153     unsigned Version =
154         (ExtInfo.MajorVersion * 1000000) + (ExtInfo.MinorVersion * 1000);
155 
156     Builder.defineMacro(Twine("__riscv_", ExtName), Twine(Version));
157   }
158 
159   if (ISAInfo->hasExtension("m")) {
160     Builder.defineMacro("__riscv_mul");
161     Builder.defineMacro("__riscv_div");
162     Builder.defineMacro("__riscv_muldiv");
163   }
164 
165   if (ISAInfo->hasExtension("a")) {
166     Builder.defineMacro("__riscv_atomic");
167     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
168     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
169     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
170     if (Is64Bit)
171       Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
172   }
173 
174   if (FLen) {
175     Builder.defineMacro("__riscv_flen", Twine(FLen));
176     Builder.defineMacro("__riscv_fdiv");
177     Builder.defineMacro("__riscv_fsqrt");
178   }
179 
180   if (MinVLen)
181     Builder.defineMacro("__riscv_v_min_vlen", Twine(MinVLen));
182 
183   if (ISAInfo->hasExtension("c"))
184     Builder.defineMacro("__riscv_compressed");
185 
186   if (ISAInfo->hasExtension("v"))
187     Builder.defineMacro("__riscv_vector");
188 }
189 
190 const Builtin::Info RISCVTargetInfo::BuiltinInfo[] = {
191 #define BUILTIN(ID, TYPE, ATTRS)                                               \
192   {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
193 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
194     {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
195 #include "clang/Basic/BuiltinsRISCVVector.def"
196 #define BUILTIN(ID, TYPE, ATTRS)                                               \
197   {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
198 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
199     {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
200 #include "clang/Basic/BuiltinsRISCV.def"
201 };
202 
203 ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const {
204   return llvm::makeArrayRef(BuiltinInfo, clang::RISCV::LastTSBuiltin -
205                                              Builtin::FirstTSBuiltin);
206 }
207 
208 bool RISCVTargetInfo::initFeatureMap(
209     llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
210     const std::vector<std::string> &FeaturesVec) const {
211 
212   if (getTriple().getArch() == llvm::Triple::riscv64)
213     Features["64bit"] = true;
214 
215   return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
216 }
217 
218 /// Return true if has this feature, need to sync with handleTargetFeatures.
219 bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
220   bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
221   auto Result = llvm::StringSwitch<Optional<bool>>(Feature)
222                     .Case("riscv", true)
223                     .Case("riscv32", !Is64Bit)
224                     .Case("riscv64", Is64Bit)
225                     .Case("64bit", Is64Bit)
226                     .Default(None);
227   if (Result.hasValue())
228     return Result.getValue();
229 
230   if (ISAInfo->isSupportedExtensionFeature(Feature))
231     return ISAInfo->hasExtension(Feature);
232 
233   return false;
234 }
235 
236 /// Perform initialization based on the user configured set of features.
237 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
238                                            DiagnosticsEngine &Diags) {
239   unsigned XLen = getTriple().isArch64Bit() ? 64 : 32;
240   auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, Features);
241   if (!ParseResult) {
242     std::string Buffer;
243     llvm::raw_string_ostream OutputErrMsg(Buffer);
244     handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
245       OutputErrMsg << ErrMsg.getMessage();
246     });
247     Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
248     return false;
249   } else {
250     ISAInfo = std::move(*ParseResult);
251   }
252 
253   if (ABI.empty())
254     ABI = llvm::RISCV::computeDefaultABIFromArch(*ISAInfo).str();
255 
256   return true;
257 }
258 
259 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const {
260   return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
261                                    /*Is64Bit=*/false);
262 }
263 
264 void RISCV32TargetInfo::fillValidCPUList(
265     SmallVectorImpl<StringRef> &Values) const {
266   llvm::RISCV::fillValidCPUArchList(Values, false);
267 }
268 
269 bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const {
270   return llvm::RISCV::checkTuneCPUKind(
271       llvm::RISCV::parseTuneCPUKind(Name, false),
272       /*Is64Bit=*/false);
273 }
274 
275 void RISCV32TargetInfo::fillValidTuneCPUList(
276     SmallVectorImpl<StringRef> &Values) const {
277   llvm::RISCV::fillValidTuneCPUArchList(Values, false);
278 }
279 
280 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
281   return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
282                                    /*Is64Bit=*/true);
283 }
284 
285 void RISCV64TargetInfo::fillValidCPUList(
286     SmallVectorImpl<StringRef> &Values) const {
287   llvm::RISCV::fillValidCPUArchList(Values, true);
288 }
289 
290 bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const {
291   return llvm::RISCV::checkTuneCPUKind(
292       llvm::RISCV::parseTuneCPUKind(Name, true),
293       /*Is64Bit=*/true);
294 }
295 
296 void RISCV64TargetInfo::fillValidTuneCPUList(
297     SmallVectorImpl<StringRef> &Values) const {
298   llvm::RISCV::fillValidTuneCPUArchList(Values, true);
299 }
300