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 '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 
convertConstraint(const char * & Constraint) const104 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 
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const118 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 (HasV) {
180     Builder.defineMacro("__riscv_v", "10000");
181     Builder.defineMacro("__riscv_vector");
182   }
183 
184   if (HasZba)
185     Builder.defineMacro("__riscv_zba", "93000");
186 
187   if (HasZbb)
188     Builder.defineMacro("__riscv_zbb", "93000");
189 
190   if (HasZbc)
191     Builder.defineMacro("__riscv_zbc", "93000");
192 
193   if (HasZbe)
194     Builder.defineMacro("__riscv_zbe", "93000");
195 
196   if (HasZbf)
197     Builder.defineMacro("__riscv_zbf", "93000");
198 
199   if (HasZbm)
200     Builder.defineMacro("__riscv_zbm", "93000");
201 
202   if (HasZbp)
203     Builder.defineMacro("__riscv_zbp", "93000");
204 
205   if (HasZbr)
206     Builder.defineMacro("__riscv_zbr", "93000");
207 
208   if (HasZbs)
209     Builder.defineMacro("__riscv_zbs", "93000");
210 
211   if (HasZbt)
212     Builder.defineMacro("__riscv_zbt", "93000");
213 
214   if (HasZfh)
215     Builder.defineMacro("__riscv_zfh", "1000");
216 
217   if (HasZvamo)
218     Builder.defineMacro("__riscv_zvamo", "10000");
219 
220   if (HasZvlsseg)
221     Builder.defineMacro("__riscv_zvlsseg", "10000");
222 }
223 
224 const Builtin::Info RISCVTargetInfo::BuiltinInfo[] = {
225 #define BUILTIN(ID, TYPE, ATTRS)                                               \
226   {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
227 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
228     {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
229 #include "clang/Basic/BuiltinsRISCV.def"
230 };
231 
getTargetBuiltins() const232 ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const {
233   return llvm::makeArrayRef(BuiltinInfo, clang::RISCV::LastTSBuiltin -
234                                              Builtin::FirstTSBuiltin);
235 }
236 
initFeatureMap(llvm::StringMap<bool> & Features,DiagnosticsEngine & Diags,StringRef CPU,const std::vector<std::string> & FeaturesVec) const237 bool RISCVTargetInfo::initFeatureMap(
238     llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
239     const std::vector<std::string> &FeaturesVec) const {
240 
241   if (getTriple().getArch() == llvm::Triple::riscv64)
242     Features["64bit"] = true;
243 
244   return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
245 }
246 
247 /// Return true if has this feature, need to sync with handleTargetFeatures.
hasFeature(StringRef Feature) const248 bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
249   bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
250   return llvm::StringSwitch<bool>(Feature)
251       .Case("riscv", true)
252       .Case("riscv32", !Is64Bit)
253       .Case("riscv64", Is64Bit)
254       .Case("64bit", Is64Bit)
255       .Case("m", HasM)
256       .Case("a", HasA)
257       .Case("f", HasF)
258       .Case("d", HasD)
259       .Case("c", HasC)
260       .Case("experimental-v", HasV)
261       .Case("experimental-zba", HasZba)
262       .Case("experimental-zbb", HasZbb)
263       .Case("experimental-zbc", HasZbc)
264       .Case("experimental-zbe", HasZbe)
265       .Case("experimental-zbf", HasZbf)
266       .Case("experimental-zbm", HasZbm)
267       .Case("experimental-zbp", HasZbp)
268       .Case("experimental-zbr", HasZbr)
269       .Case("experimental-zbs", HasZbs)
270       .Case("experimental-zbt", HasZbt)
271       .Case("experimental-zfh", HasZfh)
272       .Case("experimental-zvamo", HasZvamo)
273       .Case("experimental-zvlsseg", HasZvlsseg)
274       .Default(false);
275 }
276 
277 /// Perform initialization based on the user configured set of features.
handleTargetFeatures(std::vector<std::string> & Features,DiagnosticsEngine & Diags)278 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
279                                            DiagnosticsEngine &Diags) {
280   for (const auto &Feature : Features) {
281     if (Feature == "+m")
282       HasM = true;
283     else if (Feature == "+a")
284       HasA = true;
285     else if (Feature == "+f")
286       HasF = true;
287     else if (Feature == "+d")
288       HasD = true;
289     else if (Feature == "+c")
290       HasC = true;
291     else if (Feature == "+experimental-v")
292       HasV = true;
293     else if (Feature == "+experimental-zba")
294       HasZba = true;
295     else if (Feature == "+experimental-zbb")
296       HasZbb = true;
297     else if (Feature == "+experimental-zbc")
298       HasZbc = true;
299     else if (Feature == "+experimental-zbe")
300       HasZbe = true;
301     else if (Feature == "+experimental-zbf")
302       HasZbf = true;
303     else if (Feature == "+experimental-zbm")
304       HasZbm = true;
305     else if (Feature == "+experimental-zbp")
306       HasZbp = 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 
isValidCPUName(StringRef Name) const324 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const {
325   return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
326                                    /*Is64Bit=*/false);
327 }
328 
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const329 void RISCV32TargetInfo::fillValidCPUList(
330     SmallVectorImpl<StringRef> &Values) const {
331   llvm::RISCV::fillValidCPUArchList(Values, false);
332 }
333 
isValidTuneCPUName(StringRef Name) const334 bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const {
335   return llvm::RISCV::checkTuneCPUKind(
336       llvm::RISCV::parseTuneCPUKind(Name, false),
337       /*Is64Bit=*/false);
338 }
339 
fillValidTuneCPUList(SmallVectorImpl<StringRef> & Values) const340 void RISCV32TargetInfo::fillValidTuneCPUList(
341     SmallVectorImpl<StringRef> &Values) const {
342   llvm::RISCV::fillValidTuneCPUArchList(Values, false);
343 }
344 
isValidCPUName(StringRef Name) const345 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
346   return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
347                                    /*Is64Bit=*/true);
348 }
349 
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const350 void RISCV64TargetInfo::fillValidCPUList(
351     SmallVectorImpl<StringRef> &Values) const {
352   llvm::RISCV::fillValidCPUArchList(Values, true);
353 }
354 
isValidTuneCPUName(StringRef Name) const355 bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const {
356   return llvm::RISCV::checkTuneCPUKind(
357       llvm::RISCV::parseTuneCPUKind(Name, true),
358       /*Is64Bit=*/true);
359 }
360 
fillValidTuneCPUList(SmallVectorImpl<StringRef> & Values) const361 void RISCV64TargetInfo::fillValidTuneCPUList(
362     SmallVectorImpl<StringRef> &Values) const {
363   llvm::RISCV::fillValidTuneCPUArchList(Values, true);
364 }
365