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 'v':
91     // A vector register.
92     if (Name[1] == 'r' || Name[1] == 'm') {
93       Info.setAllowsRegister();
94       Name += 1;
95       return true;
96     }
97     return false;
98   }
99 }
100 
101 std::string RISCVTargetInfo::convertConstraint(const char *&Constraint) const {
102   std::string R;
103   switch (*Constraint) {
104   case 'v':
105     R = std::string("v");
106     Constraint += 1;
107     break;
108   default:
109     R = TargetInfo::convertConstraint(Constraint);
110     break;
111   }
112   return R;
113 }
114 
115 void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
116                                        MacroBuilder &Builder) const {
117   Builder.defineMacro("__ELF__");
118   Builder.defineMacro("__riscv");
119   bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
120   Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32");
121   StringRef CodeModel = getTargetOpts().CodeModel;
122   if (CodeModel == "default")
123     CodeModel = "small";
124 
125   if (CodeModel == "small")
126     Builder.defineMacro("__riscv_cmodel_medlow");
127   else if (CodeModel == "medium")
128     Builder.defineMacro("__riscv_cmodel_medany");
129 
130   StringRef ABIName = getABI();
131   if (ABIName == "ilp32f" || ABIName == "lp64f")
132     Builder.defineMacro("__riscv_float_abi_single");
133   else if (ABIName == "ilp32d" || ABIName == "lp64d")
134     Builder.defineMacro("__riscv_float_abi_double");
135   else
136     Builder.defineMacro("__riscv_float_abi_soft");
137 
138   if (ABIName == "ilp32e")
139     Builder.defineMacro("__riscv_abi_rve");
140 
141   Builder.defineMacro("__riscv_arch_test");
142   Builder.defineMacro("__riscv_i", "2000000");
143 
144   if (HasM) {
145     Builder.defineMacro("__riscv_m", "2000000");
146     Builder.defineMacro("__riscv_mul");
147     Builder.defineMacro("__riscv_div");
148     Builder.defineMacro("__riscv_muldiv");
149   }
150 
151   if (HasA) {
152     Builder.defineMacro("__riscv_a", "2000000");
153     Builder.defineMacro("__riscv_atomic");
154     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
155     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
156     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
157     if (Is64Bit)
158       Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
159   }
160 
161   if (HasF || HasD) {
162     Builder.defineMacro("__riscv_f", "2000000");
163     Builder.defineMacro("__riscv_flen", HasD ? "64" : "32");
164     Builder.defineMacro("__riscv_fdiv");
165     Builder.defineMacro("__riscv_fsqrt");
166   }
167 
168   if (HasD)
169     Builder.defineMacro("__riscv_d", "2000000");
170 
171   if (HasC) {
172     Builder.defineMacro("__riscv_c", "2000000");
173     Builder.defineMacro("__riscv_compressed");
174   }
175 
176   if (HasB) {
177     Builder.defineMacro("__riscv_b", "93000");
178     Builder.defineMacro("__riscv_bitmanip");
179   }
180 
181   if (HasV) {
182     Builder.defineMacro("__riscv_v", "10000");
183     Builder.defineMacro("__riscv_vector");
184   }
185 
186   if (HasZba)
187     Builder.defineMacro("__riscv_zba", "93000");
188 
189   if (HasZbb)
190     Builder.defineMacro("__riscv_zbb", "93000");
191 
192   if (HasZbc)
193     Builder.defineMacro("__riscv_zbc", "93000");
194 
195   if (HasZbe)
196     Builder.defineMacro("__riscv_zbe", "93000");
197 
198   if (HasZbf)
199     Builder.defineMacro("__riscv_zbf", "93000");
200 
201   if (HasZbm)
202     Builder.defineMacro("__riscv_zbm", "93000");
203 
204   if (HasZbp)
205     Builder.defineMacro("__riscv_zbp", "93000");
206 
207   if (HasZbproposedc)
208     Builder.defineMacro("__riscv_zbproposedc", "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 /// Return true if has this feature, need to sync with handleTargetFeatures.
243 bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
244   bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
245   return llvm::StringSwitch<bool>(Feature)
246       .Case("riscv", true)
247       .Case("riscv32", !Is64Bit)
248       .Case("riscv64", Is64Bit)
249       .Case("m", HasM)
250       .Case("a", HasA)
251       .Case("f", HasF)
252       .Case("d", HasD)
253       .Case("c", HasC)
254       .Case("experimental-b", HasB)
255       .Case("experimental-v", HasV)
256       .Case("experimental-zba", HasZba)
257       .Case("experimental-zbb", HasZbb)
258       .Case("experimental-zbc", HasZbc)
259       .Case("experimental-zbe", HasZbe)
260       .Case("experimental-zbf", HasZbf)
261       .Case("experimental-zbm", HasZbm)
262       .Case("experimental-zbp", HasZbp)
263       .Case("experimental-zbproposedc", HasZbproposedc)
264       .Case("experimental-zbr", HasZbr)
265       .Case("experimental-zbs", HasZbs)
266       .Case("experimental-zbt", HasZbt)
267       .Case("experimental-zfh", HasZfh)
268       .Case("experimental-zvamo", HasZvamo)
269       .Case("experimental-zvlsseg", HasZvlsseg)
270       .Default(false);
271 }
272 
273 /// Perform initialization based on the user configured set of features.
274 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
275                                            DiagnosticsEngine &Diags) {
276   for (const auto &Feature : Features) {
277     if (Feature == "+m")
278       HasM = true;
279     else if (Feature == "+a")
280       HasA = true;
281     else if (Feature == "+f")
282       HasF = true;
283     else if (Feature == "+d")
284       HasD = true;
285     else if (Feature == "+c")
286       HasC = true;
287     else if (Feature == "+experimental-b")
288       HasB = true;
289     else if (Feature == "+experimental-v")
290       HasV = true;
291     else if (Feature == "+experimental-zba")
292       HasZba = true;
293     else if (Feature == "+experimental-zbb")
294       HasZbb = true;
295     else if (Feature == "+experimental-zbc")
296       HasZbc = true;
297     else if (Feature == "+experimental-zbe")
298       HasZbe = true;
299     else if (Feature == "+experimental-zbf")
300       HasZbf = true;
301     else if (Feature == "+experimental-zbm")
302       HasZbm = true;
303     else if (Feature == "+experimental-zbp")
304       HasZbp = true;
305     else if (Feature == "+experimental-zbproposedc")
306       HasZbproposedc = true;
307     else if (Feature == "+experimental-zbr")
308       HasZbr = true;
309     else if (Feature == "+experimental-zbs")
310       HasZbs = true;
311     else if (Feature == "+experimental-zbt")
312       HasZbt = true;
313     else if (Feature == "+experimental-zfh")
314       HasZfh = true;
315     else if (Feature == "+experimental-zvamo")
316       HasZvamo = true;
317     else if (Feature == "+experimental-zvlsseg")
318       HasZvlsseg = true;
319   }
320 
321   return true;
322 }
323 
324 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const {
325   return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
326                                    /*Is64Bit=*/false);
327 }
328 
329 void RISCV32TargetInfo::fillValidCPUList(
330     SmallVectorImpl<StringRef> &Values) const {
331   llvm::RISCV::fillValidCPUArchList(Values, false);
332 }
333 
334 bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const {
335   return llvm::RISCV::checkTuneCPUKind(
336       llvm::RISCV::parseTuneCPUKind(Name, false),
337       /*Is64Bit=*/false);
338 }
339 
340 void RISCV32TargetInfo::fillValidTuneCPUList(
341     SmallVectorImpl<StringRef> &Values) const {
342   llvm::RISCV::fillValidTuneCPUArchList(Values, false);
343 }
344 
345 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
346   return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
347                                    /*Is64Bit=*/true);
348 }
349 
350 void RISCV64TargetInfo::fillValidCPUList(
351     SmallVectorImpl<StringRef> &Values) const {
352   llvm::RISCV::fillValidCPUArchList(Values, true);
353 }
354 
355 bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const {
356   return llvm::RISCV::checkTuneCPUKind(
357       llvm::RISCV::parseTuneCPUKind(Name, true),
358       /*Is64Bit=*/true);
359 }
360 
361 void RISCV64TargetInfo::fillValidTuneCPUList(
362     SmallVectorImpl<StringRef> &Values) const {
363   llvm::RISCV::fillValidTuneCPUArchList(Values, true);
364 }
365