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/MacroBuilder.h"
15 #include "clang/Basic/TargetBuiltins.h"
16 #include "llvm/ADT/StringSwitch.h"
17 #include "llvm/Support/TargetParser.h"
18 
19 using namespace clang;
20 using namespace clang::targets;
21 
22 ArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const {
23   static const char *const GCCRegNames[] = {
24       // Integer registers
25       "x0",  "x1",  "x2",  "x3",  "x4",  "x5",  "x6",  "x7",
26       "x8",  "x9",  "x10", "x11", "x12", "x13", "x14", "x15",
27       "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
28       "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31",
29 
30       // Floating point registers
31       "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
32       "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",
33       "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
34       "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
35 
36       // Vector registers
37       "v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6",  "v7",
38       "v8",  "v9",  "v10", "v11", "v12", "v13", "v14", "v15",
39       "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
40       "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"};
41   return llvm::makeArrayRef(GCCRegNames);
42 }
43 
44 ArrayRef<TargetInfo::GCCRegAlias> RISCVTargetInfo::getGCCRegAliases() const {
45   static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
46       {{"zero"}, "x0"}, {{"ra"}, "x1"},   {{"sp"}, "x2"},    {{"gp"}, "x3"},
47       {{"tp"}, "x4"},   {{"t0"}, "x5"},   {{"t1"}, "x6"},    {{"t2"}, "x7"},
48       {{"s0"}, "x8"},   {{"s1"}, "x9"},   {{"a0"}, "x10"},   {{"a1"}, "x11"},
49       {{"a2"}, "x12"},  {{"a3"}, "x13"},  {{"a4"}, "x14"},   {{"a5"}, "x15"},
50       {{"a6"}, "x16"},  {{"a7"}, "x17"},  {{"s2"}, "x18"},   {{"s3"}, "x19"},
51       {{"s4"}, "x20"},  {{"s5"}, "x21"},  {{"s6"}, "x22"},   {{"s7"}, "x23"},
52       {{"s8"}, "x24"},  {{"s9"}, "x25"},  {{"s10"}, "x26"},  {{"s11"}, "x27"},
53       {{"t3"}, "x28"},  {{"t4"}, "x29"},  {{"t5"}, "x30"},   {{"t6"}, "x31"},
54       {{"ft0"}, "f0"},  {{"ft1"}, "f1"},  {{"ft2"}, "f2"},   {{"ft3"}, "f3"},
55       {{"ft4"}, "f4"},  {{"ft5"}, "f5"},  {{"ft6"}, "f6"},   {{"ft7"}, "f7"},
56       {{"fs0"}, "f8"},  {{"fs1"}, "f9"},  {{"fa0"}, "f10"},  {{"fa1"}, "f11"},
57       {{"fa2"}, "f12"}, {{"fa3"}, "f13"}, {{"fa4"}, "f14"},  {{"fa5"}, "f15"},
58       {{"fa6"}, "f16"}, {{"fa7"}, "f17"}, {{"fs2"}, "f18"},  {{"fs3"}, "f19"},
59       {{"fs4"}, "f20"}, {{"fs5"}, "f21"}, {{"fs6"}, "f22"},  {{"fs7"}, "f23"},
60       {{"fs8"}, "f24"}, {{"fs9"}, "f25"}, {{"fs10"}, "f26"}, {{"fs11"}, "f27"},
61       {{"ft8"}, "f28"}, {{"ft9"}, "f29"}, {{"ft10"}, "f30"}, {{"ft11"}, "f31"}};
62   return llvm::makeArrayRef(GCCRegAliases);
63 }
64 
65 bool RISCVTargetInfo::validateAsmConstraint(
66     const char *&Name, TargetInfo::ConstraintInfo &Info) const {
67   switch (*Name) {
68   default:
69     return false;
70   case 'I':
71     // A 12-bit signed immediate.
72     Info.setRequiresImmediate(-2048, 2047);
73     return true;
74   case 'J':
75     // Integer zero.
76     Info.setRequiresImmediate(0);
77     return true;
78   case 'K':
79     // A 5-bit unsigned immediate for CSR access instructions.
80     Info.setRequiresImmediate(0, 31);
81     return true;
82   case 'f':
83     // A floating-point register.
84     Info.setAllowsRegister();
85     return true;
86   case 'A':
87     // An address that is held in a general-purpose register.
88     Info.setAllowsMemory();
89     return true;
90   case 'S': // A symbolic address
91     Info.setAllowsRegister();
92     return true;
93   case 'v':
94     // A vector register.
95     if (Name[1] == 'r' || Name[1] == 'm') {
96       Info.setAllowsRegister();
97       Name += 1;
98       return true;
99     }
100     return false;
101   }
102 }
103 
104 std::string RISCVTargetInfo::convertConstraint(const char *&Constraint) const {
105   std::string R;
106   switch (*Constraint) {
107   case 'v':
108     R = std::string("v");
109     Constraint += 1;
110     break;
111   default:
112     R = TargetInfo::convertConstraint(Constraint);
113     break;
114   }
115   return R;
116 }
117 
118 void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
119                                        MacroBuilder &Builder) const {
120   Builder.defineMacro("__ELF__");
121   Builder.defineMacro("__riscv");
122   bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
123   Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32");
124   StringRef CodeModel = getTargetOpts().CodeModel;
125   if (CodeModel == "default")
126     CodeModel = "small";
127 
128   if (CodeModel == "small")
129     Builder.defineMacro("__riscv_cmodel_medlow");
130   else if (CodeModel == "medium")
131     Builder.defineMacro("__riscv_cmodel_medany");
132 
133   StringRef ABIName = getABI();
134   if (ABIName == "ilp32f" || ABIName == "lp64f")
135     Builder.defineMacro("__riscv_float_abi_single");
136   else if (ABIName == "ilp32d" || ABIName == "lp64d")
137     Builder.defineMacro("__riscv_float_abi_double");
138   else
139     Builder.defineMacro("__riscv_float_abi_soft");
140 
141   if (ABIName == "ilp32e")
142     Builder.defineMacro("__riscv_abi_rve");
143 
144   Builder.defineMacro("__riscv_arch_test");
145   Builder.defineMacro("__riscv_i", "2000000");
146 
147   if (HasM) {
148     Builder.defineMacro("__riscv_m", "2000000");
149     Builder.defineMacro("__riscv_mul");
150     Builder.defineMacro("__riscv_div");
151     Builder.defineMacro("__riscv_muldiv");
152   }
153 
154   if (HasA) {
155     Builder.defineMacro("__riscv_a", "2000000");
156     Builder.defineMacro("__riscv_atomic");
157     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
158     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
159     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
160     if (Is64Bit)
161       Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
162   }
163 
164   if (HasF || HasD) {
165     Builder.defineMacro("__riscv_f", "2000000");
166     Builder.defineMacro("__riscv_flen", HasD ? "64" : "32");
167     Builder.defineMacro("__riscv_fdiv");
168     Builder.defineMacro("__riscv_fsqrt");
169   }
170 
171   if (HasD)
172     Builder.defineMacro("__riscv_d", "2000000");
173 
174   if (HasC) {
175     Builder.defineMacro("__riscv_c", "2000000");
176     Builder.defineMacro("__riscv_compressed");
177   }
178 
179   if (HasB) {
180     Builder.defineMacro("__riscv_b", "93000");
181     Builder.defineMacro("__riscv_bitmanip");
182   }
183 
184   if (HasV) {
185     Builder.defineMacro("__riscv_v", "10000");
186     Builder.defineMacro("__riscv_vector");
187   }
188 
189   if (HasZba)
190     Builder.defineMacro("__riscv_zba", "93000");
191 
192   if (HasZbb)
193     Builder.defineMacro("__riscv_zbb", "93000");
194 
195   if (HasZbc)
196     Builder.defineMacro("__riscv_zbc", "93000");
197 
198   if (HasZbe)
199     Builder.defineMacro("__riscv_zbe", "93000");
200 
201   if (HasZbf)
202     Builder.defineMacro("__riscv_zbf", "93000");
203 
204   if (HasZbm)
205     Builder.defineMacro("__riscv_zbm", "93000");
206 
207   if (HasZbp)
208     Builder.defineMacro("__riscv_zbp", "93000");
209 
210   if (HasZbproposedc)
211     Builder.defineMacro("__riscv_zbproposedc", "93000");
212 
213   if (HasZbr)
214     Builder.defineMacro("__riscv_zbr", "93000");
215 
216   if (HasZbs)
217     Builder.defineMacro("__riscv_zbs", "93000");
218 
219   if (HasZbt)
220     Builder.defineMacro("__riscv_zbt", "93000");
221 
222   if (HasZfh)
223     Builder.defineMacro("__riscv_zfh", "1000");
224 
225   if (HasZvamo)
226     Builder.defineMacro("__riscv_zvamo", "10000");
227 
228   if (HasZvlsseg)
229     Builder.defineMacro("__riscv_zvlsseg", "10000");
230 }
231 
232 const Builtin::Info RISCVTargetInfo::BuiltinInfo[] = {
233 #define BUILTIN(ID, TYPE, ATTRS)                                               \
234   {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
235 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
236     {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
237 #include "clang/Basic/BuiltinsRISCV.def"
238 };
239 
240 ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const {
241   return llvm::makeArrayRef(BuiltinInfo, clang::RISCV::LastTSBuiltin -
242                                              Builtin::FirstTSBuiltin);
243 }
244 
245 bool RISCVTargetInfo::initFeatureMap(
246     llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
247     const std::vector<std::string> &FeaturesVec) const {
248 
249   if (getTriple().getArch() == llvm::Triple::riscv64)
250     Features["64bit"] = true;
251 
252   return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
253 }
254 
255 /// Return true if has this feature, need to sync with handleTargetFeatures.
256 bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
257   bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
258   return llvm::StringSwitch<bool>(Feature)
259       .Case("riscv", true)
260       .Case("riscv32", !Is64Bit)
261       .Case("riscv64", Is64Bit)
262       .Case("64bit", Is64Bit)
263       .Case("m", HasM)
264       .Case("a", HasA)
265       .Case("f", HasF)
266       .Case("d", HasD)
267       .Case("c", HasC)
268       .Case("experimental-b", HasB)
269       .Case("experimental-v", HasV)
270       .Case("experimental-zba", HasZba)
271       .Case("experimental-zbb", HasZbb)
272       .Case("experimental-zbc", HasZbc)
273       .Case("experimental-zbe", HasZbe)
274       .Case("experimental-zbf", HasZbf)
275       .Case("experimental-zbm", HasZbm)
276       .Case("experimental-zbp", HasZbp)
277       .Case("experimental-zbproposedc", HasZbproposedc)
278       .Case("experimental-zbr", HasZbr)
279       .Case("experimental-zbs", HasZbs)
280       .Case("experimental-zbt", HasZbt)
281       .Case("experimental-zfh", HasZfh)
282       .Case("experimental-zvamo", HasZvamo)
283       .Case("experimental-zvlsseg", HasZvlsseg)
284       .Default(false);
285 }
286 
287 /// Perform initialization based on the user configured set of features.
288 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
289                                            DiagnosticsEngine &Diags) {
290   for (const auto &Feature : Features) {
291     if (Feature == "+m")
292       HasM = true;
293     else if (Feature == "+a")
294       HasA = true;
295     else if (Feature == "+f")
296       HasF = true;
297     else if (Feature == "+d")
298       HasD = true;
299     else if (Feature == "+c")
300       HasC = true;
301     else if (Feature == "+experimental-b")
302       HasB = true;
303     else if (Feature == "+experimental-v")
304       HasV = true;
305     else if (Feature == "+experimental-zba")
306       HasZba = true;
307     else if (Feature == "+experimental-zbb")
308       HasZbb = true;
309     else if (Feature == "+experimental-zbc")
310       HasZbc = true;
311     else if (Feature == "+experimental-zbe")
312       HasZbe = true;
313     else if (Feature == "+experimental-zbf")
314       HasZbf = true;
315     else if (Feature == "+experimental-zbm")
316       HasZbm = true;
317     else if (Feature == "+experimental-zbp")
318       HasZbp = true;
319     else if (Feature == "+experimental-zbproposedc")
320       HasZbproposedc = true;
321     else if (Feature == "+experimental-zbr")
322       HasZbr = true;
323     else if (Feature == "+experimental-zbs")
324       HasZbs = true;
325     else if (Feature == "+experimental-zbt")
326       HasZbt = true;
327     else if (Feature == "+experimental-zfh")
328       HasZfh = true;
329     else if (Feature == "+experimental-zvamo")
330       HasZvamo = true;
331     else if (Feature == "+experimental-zvlsseg")
332       HasZvlsseg = true;
333   }
334 
335   return true;
336 }
337 
338 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const {
339   return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
340                                    /*Is64Bit=*/false);
341 }
342 
343 void RISCV32TargetInfo::fillValidCPUList(
344     SmallVectorImpl<StringRef> &Values) const {
345   llvm::RISCV::fillValidCPUArchList(Values, false);
346 }
347 
348 bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const {
349   return llvm::RISCV::checkTuneCPUKind(
350       llvm::RISCV::parseTuneCPUKind(Name, false),
351       /*Is64Bit=*/false);
352 }
353 
354 void RISCV32TargetInfo::fillValidTuneCPUList(
355     SmallVectorImpl<StringRef> &Values) const {
356   llvm::RISCV::fillValidTuneCPUArchList(Values, false);
357 }
358 
359 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
360   return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
361                                    /*Is64Bit=*/true);
362 }
363 
364 void RISCV64TargetInfo::fillValidCPUList(
365     SmallVectorImpl<StringRef> &Values) const {
366   llvm::RISCV::fillValidCPUArchList(Values, true);
367 }
368 
369 bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const {
370   return llvm::RISCV::checkTuneCPUKind(
371       llvm::RISCV::parseTuneCPUKind(Name, true),
372       /*Is64Bit=*/true);
373 }
374 
375 void RISCV64TargetInfo::fillValidTuneCPUList(
376     SmallVectorImpl<StringRef> &Values) const {
377   llvm::RISCV::fillValidTuneCPUArchList(Values, true);
378 }
379