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
19using namespace clang;
20using namespace clang::targets;
21
22ArrayRef<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
44ArrayRef<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
65bool 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
101std::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
115void 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
229const 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
237ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const {
238  return llvm::makeArrayRef(BuiltinInfo, clang::RISCV::LastTSBuiltin -
239                                             Builtin::FirstTSBuiltin);
240}
241
242bool 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.
253bool 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.
285bool 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
335bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const {
336  return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
337                                   /*Is64Bit=*/false);
338}
339
340void RISCV32TargetInfo::fillValidCPUList(
341    SmallVectorImpl<StringRef> &Values) const {
342  llvm::RISCV::fillValidCPUArchList(Values, false);
343}
344
345bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const {
346  return llvm::RISCV::checkTuneCPUKind(
347      llvm::RISCV::parseTuneCPUKind(Name, false),
348      /*Is64Bit=*/false);
349}
350
351void RISCV32TargetInfo::fillValidTuneCPUList(
352    SmallVectorImpl<StringRef> &Values) const {
353  llvm::RISCV::fillValidTuneCPUArchList(Values, false);
354}
355
356bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
357  return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
358                                   /*Is64Bit=*/true);
359}
360
361void RISCV64TargetInfo::fillValidCPUList(
362    SmallVectorImpl<StringRef> &Values) const {
363  llvm::RISCV::fillValidCPUArchList(Values, true);
364}
365
366bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const {
367  return llvm::RISCV::checkTuneCPUKind(
368      llvm::RISCV::parseTuneCPUKind(Name, true),
369      /*Is64Bit=*/true);
370}
371
372void RISCV64TargetInfo::fillValidTuneCPUList(
373    SmallVectorImpl<StringRef> &Values) const {
374  llvm::RISCV::fillValidTuneCPUArchList(Values, true);
375}
376