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("^") + std::string(Constraint, 2);
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 (HasZbr)
211     Builder.defineMacro("__riscv_zbr", "93000");
212 
213   if (HasZbs)
214     Builder.defineMacro("__riscv_zbs", "93000");
215 
216   if (HasZbt)
217     Builder.defineMacro("__riscv_zbt", "93000");
218 
219   if (HasZfh)
220     Builder.defineMacro("__riscv_zfh", "1000");
221 
222   if (HasZvamo)
223     Builder.defineMacro("__riscv_zvamo", "10000");
224 
225   if (HasZvlsseg)
226     Builder.defineMacro("__riscv_zvlsseg", "10000");
227 }
228 
229 const Builtin::Info RISCVTargetInfo::BuiltinInfo[] = {
230 #define BUILTIN(ID, TYPE, ATTRS)                                               \
231   {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
232 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
233     {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
234 #include "clang/Basic/BuiltinsRISCV.def"
235 };
236 
237 ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const {
238   return llvm::makeArrayRef(BuiltinInfo, clang::RISCV::LastTSBuiltin -
239                                              Builtin::FirstTSBuiltin);
240 }
241 
242 bool RISCVTargetInfo::initFeatureMap(
243     llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
244     const std::vector<std::string> &FeaturesVec) const {
245 
246   if (getTriple().getArch() == llvm::Triple::riscv64)
247     Features["64bit"] = true;
248 
249   return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
250 }
251 
252 /// Return true if has this feature, need to sync with handleTargetFeatures.
253 bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
254   bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
255   return llvm::StringSwitch<bool>(Feature)
256       .Case("riscv", true)
257       .Case("riscv32", !Is64Bit)
258       .Case("riscv64", Is64Bit)
259       .Case("64bit", Is64Bit)
260       .Case("m", HasM)
261       .Case("a", HasA)
262       .Case("f", HasF)
263       .Case("d", HasD)
264       .Case("c", HasC)
265       .Case("experimental-b", HasB)
266       .Case("experimental-v", HasV)
267       .Case("experimental-zba", HasZba)
268       .Case("experimental-zbb", HasZbb)
269       .Case("experimental-zbc", HasZbc)
270       .Case("experimental-zbe", HasZbe)
271       .Case("experimental-zbf", HasZbf)
272       .Case("experimental-zbm", HasZbm)
273       .Case("experimental-zbp", HasZbp)
274       .Case("experimental-zbr", HasZbr)
275       .Case("experimental-zbs", HasZbs)
276       .Case("experimental-zbt", HasZbt)
277       .Case("experimental-zfh", HasZfh)
278       .Case("experimental-zvamo", HasZvamo)
279       .Case("experimental-zvlsseg", HasZvlsseg)
280       .Default(false);
281 }
282 
283 /// Perform initialization based on the user configured set of features.
284 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
285                                            DiagnosticsEngine &Diags) {
286   for (const auto &Feature : Features) {
287     if (Feature == "+m")
288       HasM = true;
289     else if (Feature == "+a")
290       HasA = true;
291     else if (Feature == "+f")
292       HasF = true;
293     else if (Feature == "+d")
294       HasD = true;
295     else if (Feature == "+c")
296       HasC = true;
297     else if (Feature == "+experimental-b")
298       HasB = true;
299     else if (Feature == "+experimental-v")
300       HasV = true;
301     else if (Feature == "+experimental-zba")
302       HasZba = true;
303     else if (Feature == "+experimental-zbb")
304       HasZbb = true;
305     else if (Feature == "+experimental-zbc")
306       HasZbc = true;
307     else if (Feature == "+experimental-zbe")
308       HasZbe = true;
309     else if (Feature == "+experimental-zbf")
310       HasZbf = true;
311     else if (Feature == "+experimental-zbm")
312       HasZbm = true;
313     else if (Feature == "+experimental-zbp")
314       HasZbp = true;
315     else if (Feature == "+experimental-zbr")
316       HasZbr = true;
317     else if (Feature == "+experimental-zbs")
318       HasZbs = true;
319     else if (Feature == "+experimental-zbt")
320       HasZbt = true;
321     else if (Feature == "+experimental-zfh")
322       HasZfh = true;
323     else if (Feature == "+experimental-zvamo")
324       HasZvamo = true;
325     else if (Feature == "+experimental-zvlsseg")
326       HasZvlsseg = true;
327   }
328 
329   return true;
330 }
331 
332 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const {
333   return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
334                                    /*Is64Bit=*/false);
335 }
336 
337 void RISCV32TargetInfo::fillValidCPUList(
338     SmallVectorImpl<StringRef> &Values) const {
339   llvm::RISCV::fillValidCPUArchList(Values, false);
340 }
341 
342 bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const {
343   return llvm::RISCV::checkTuneCPUKind(
344       llvm::RISCV::parseTuneCPUKind(Name, false),
345       /*Is64Bit=*/false);
346 }
347 
348 void RISCV32TargetInfo::fillValidTuneCPUList(
349     SmallVectorImpl<StringRef> &Values) const {
350   llvm::RISCV::fillValidTuneCPUArchList(Values, false);
351 }
352 
353 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
354   return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
355                                    /*Is64Bit=*/true);
356 }
357 
358 void RISCV64TargetInfo::fillValidCPUList(
359     SmallVectorImpl<StringRef> &Values) const {
360   llvm::RISCV::fillValidCPUArchList(Values, true);
361 }
362 
363 bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const {
364   return llvm::RISCV::checkTuneCPUKind(
365       llvm::RISCV::parseTuneCPUKind(Name, true),
366       /*Is64Bit=*/true);
367 }
368 
369 void RISCV64TargetInfo::fillValidTuneCPUList(
370     SmallVectorImpl<StringRef> &Values) const {
371   llvm::RISCV::fillValidTuneCPUArchList(Values, true);
372 }
373