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