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 #include "clang/Basic/BuiltinsRISCV.def"
205 };
206 
207 ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const {
208   return llvm::makeArrayRef(BuiltinInfo, clang::RISCV::LastTSBuiltin -
209                                              Builtin::FirstTSBuiltin);
210 }
211 
212 /// Return true if has this feature, need to sync with handleTargetFeatures.
213 bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
214   bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
215   return llvm::StringSwitch<bool>(Feature)
216       .Case("riscv", true)
217       .Case("riscv32", !Is64Bit)
218       .Case("riscv64", Is64Bit)
219       .Case("m", HasM)
220       .Case("a", HasA)
221       .Case("f", HasF)
222       .Case("d", HasD)
223       .Case("c", HasC)
224       .Case("experimental-b", HasB)
225       .Case("experimental-v", HasV)
226       .Case("experimental-zba", HasZba)
227       .Case("experimental-zbb", HasZbb)
228       .Case("experimental-zbc", HasZbc)
229       .Case("experimental-zbe", HasZbe)
230       .Case("experimental-zbf", HasZbf)
231       .Case("experimental-zbm", HasZbm)
232       .Case("experimental-zbp", HasZbp)
233       .Case("experimental-zbproposedc", HasZbproposedc)
234       .Case("experimental-zbr", HasZbr)
235       .Case("experimental-zbs", HasZbs)
236       .Case("experimental-zbt", HasZbt)
237       .Case("experimental-zfh", HasZfh)
238       .Case("experimental-zvamo", HasZvamo)
239       .Case("experimental-zvlsseg", HasZvlsseg)
240       .Default(false);
241 }
242 
243 /// Perform initialization based on the user configured set of features.
244 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
245                                            DiagnosticsEngine &Diags) {
246   for (const auto &Feature : Features) {
247     if (Feature == "+m")
248       HasM = true;
249     else if (Feature == "+a")
250       HasA = true;
251     else if (Feature == "+f")
252       HasF = true;
253     else if (Feature == "+d")
254       HasD = true;
255     else if (Feature == "+c")
256       HasC = true;
257     else if (Feature == "+experimental-b")
258       HasB = true;
259     else if (Feature == "+experimental-v")
260       HasV = true;
261     else if (Feature == "+experimental-zba")
262       HasZba = true;
263     else if (Feature == "+experimental-zbb")
264       HasZbb = true;
265     else if (Feature == "+experimental-zbc")
266       HasZbc = true;
267     else if (Feature == "+experimental-zbe")
268       HasZbe = true;
269     else if (Feature == "+experimental-zbf")
270       HasZbf = true;
271     else if (Feature == "+experimental-zbm")
272       HasZbm = true;
273     else if (Feature == "+experimental-zbp")
274       HasZbp = true;
275     else if (Feature == "+experimental-zbproposedc")
276       HasZbproposedc = true;
277     else if (Feature == "+experimental-zbr")
278       HasZbr = true;
279     else if (Feature == "+experimental-zbs")
280       HasZbs = true;
281     else if (Feature == "+experimental-zbt")
282       HasZbt = true;
283     else if (Feature == "+experimental-zfh")
284       HasZfh = true;
285     else if (Feature == "+experimental-zvamo")
286       HasZvamo = true;
287     else if (Feature == "+experimental-zvlsseg")
288       HasZvlsseg = true;
289   }
290 
291   return true;
292 }
293 
294 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const {
295   return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
296                                    /*Is64Bit=*/false);
297 }
298 
299 void RISCV32TargetInfo::fillValidCPUList(
300     SmallVectorImpl<StringRef> &Values) const {
301   llvm::RISCV::fillValidCPUArchList(Values, false);
302 }
303 
304 bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const {
305   return llvm::RISCV::checkTuneCPUKind(
306       llvm::RISCV::parseTuneCPUKind(Name, false),
307       /*Is64Bit=*/false);
308 }
309 
310 void RISCV32TargetInfo::fillValidTuneCPUList(
311     SmallVectorImpl<StringRef> &Values) const {
312   llvm::RISCV::fillValidTuneCPUArchList(Values, false);
313 }
314 
315 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
316   return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
317                                    /*Is64Bit=*/true);
318 }
319 
320 void RISCV64TargetInfo::fillValidCPUList(
321     SmallVectorImpl<StringRef> &Values) const {
322   llvm::RISCV::fillValidCPUArchList(Values, true);
323 }
324 
325 bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const {
326   return llvm::RISCV::checkTuneCPUKind(
327       llvm::RISCV::parseTuneCPUKind(Name, true),
328       /*Is64Bit=*/true);
329 }
330 
331 void RISCV64TargetInfo::fillValidTuneCPUList(
332     SmallVectorImpl<StringRef> &Values) const {
333   llvm::RISCV::fillValidTuneCPUArchList(Values, true);
334 }
335