xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/Basic/Targets/RISCV.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
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 
getGCCRegNames() const22 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 
getGCCRegAliases() const44 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 
validateAsmConstraint(const char * & Name,TargetInfo::ConstraintInfo & Info) const65 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 
convertConstraint(const char * & Constraint) const101 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 
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const115 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 
getTargetBuiltins() const237 ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const {
238   return llvm::makeArrayRef(BuiltinInfo, clang::RISCV::LastTSBuiltin -
239                                              Builtin::FirstTSBuiltin);
240 }
241 
initFeatureMap(llvm::StringMap<bool> & Features,DiagnosticsEngine & Diags,StringRef CPU,const std::vector<std::string> & FeaturesVec) const242 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.
hasFeature(StringRef Feature) const253 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-zbproposedc", HasZbproposedc)
275       .Case("experimental-zbr", HasZbr)
276       .Case("experimental-zbs", HasZbs)
277       .Case("experimental-zbt", HasZbt)
278       .Case("experimental-zfh", HasZfh)
279       .Case("experimental-zvamo", HasZvamo)
280       .Case("experimental-zvlsseg", HasZvlsseg)
281       .Default(false);
282 }
283 
284 /// Perform initialization based on the user configured set of features.
handleTargetFeatures(std::vector<std::string> & Features,DiagnosticsEngine & Diags)285 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
286                                            DiagnosticsEngine &Diags) {
287   for (const auto &Feature : Features) {
288     if (Feature == "+m")
289       HasM = true;
290     else if (Feature == "+a")
291       HasA = true;
292     else if (Feature == "+f")
293       HasF = true;
294     else if (Feature == "+d")
295       HasD = true;
296     else if (Feature == "+c")
297       HasC = true;
298     else if (Feature == "+experimental-b")
299       HasB = true;
300     else if (Feature == "+experimental-v")
301       HasV = true;
302     else if (Feature == "+experimental-zba")
303       HasZba = true;
304     else if (Feature == "+experimental-zbb")
305       HasZbb = true;
306     else if (Feature == "+experimental-zbc")
307       HasZbc = true;
308     else if (Feature == "+experimental-zbe")
309       HasZbe = true;
310     else if (Feature == "+experimental-zbf")
311       HasZbf = true;
312     else if (Feature == "+experimental-zbm")
313       HasZbm = true;
314     else if (Feature == "+experimental-zbp")
315       HasZbp = true;
316     else if (Feature == "+experimental-zbproposedc")
317       HasZbproposedc = true;
318     else if (Feature == "+experimental-zbr")
319       HasZbr = true;
320     else if (Feature == "+experimental-zbs")
321       HasZbs = true;
322     else if (Feature == "+experimental-zbt")
323       HasZbt = true;
324     else if (Feature == "+experimental-zfh")
325       HasZfh = true;
326     else if (Feature == "+experimental-zvamo")
327       HasZvamo = true;
328     else if (Feature == "+experimental-zvlsseg")
329       HasZvlsseg = true;
330   }
331 
332   return true;
333 }
334 
isValidCPUName(StringRef Name) const335 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const {
336   return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
337                                    /*Is64Bit=*/false);
338 }
339 
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const340 void RISCV32TargetInfo::fillValidCPUList(
341     SmallVectorImpl<StringRef> &Values) const {
342   llvm::RISCV::fillValidCPUArchList(Values, false);
343 }
344 
isValidTuneCPUName(StringRef Name) const345 bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const {
346   return llvm::RISCV::checkTuneCPUKind(
347       llvm::RISCV::parseTuneCPUKind(Name, false),
348       /*Is64Bit=*/false);
349 }
350 
fillValidTuneCPUList(SmallVectorImpl<StringRef> & Values) const351 void RISCV32TargetInfo::fillValidTuneCPUList(
352     SmallVectorImpl<StringRef> &Values) const {
353   llvm::RISCV::fillValidTuneCPUArchList(Values, false);
354 }
355 
isValidCPUName(StringRef Name) const356 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
357   return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
358                                    /*Is64Bit=*/true);
359 }
360 
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const361 void RISCV64TargetInfo::fillValidCPUList(
362     SmallVectorImpl<StringRef> &Values) const {
363   llvm::RISCV::fillValidCPUArchList(Values, true);
364 }
365 
isValidTuneCPUName(StringRef Name) const366 bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const {
367   return llvm::RISCV::checkTuneCPUKind(
368       llvm::RISCV::parseTuneCPUKind(Name, true),
369       /*Is64Bit=*/true);
370 }
371 
fillValidTuneCPUList(SmallVectorImpl<StringRef> & Values) const372 void RISCV64TargetInfo::fillValidTuneCPUList(
373     SmallVectorImpl<StringRef> &Values) const {
374   llvm::RISCV::fillValidTuneCPUArchList(Values, true);
375 }
376