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 "llvm/ADT/StringSwitch.h"
16#include "llvm/Support/TargetParser.h"
17
18using namespace clang;
19using namespace clang::targets;
20
21ArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const {
22  static const char *const GCCRegNames[] = {
23      // Integer registers
24      "x0",  "x1",  "x2",  "x3",  "x4",  "x5",  "x6",  "x7",
25      "x8",  "x9",  "x10", "x11", "x12", "x13", "x14", "x15",
26      "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
27      "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31",
28
29      // Floating point registers
30      "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
31      "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",
32      "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
33      "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"};
34  return llvm::makeArrayRef(GCCRegNames);
35}
36
37ArrayRef<TargetInfo::GCCRegAlias> RISCVTargetInfo::getGCCRegAliases() const {
38  static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
39      {{"zero"}, "x0"}, {{"ra"}, "x1"},   {{"sp"}, "x2"},    {{"gp"}, "x3"},
40      {{"tp"}, "x4"},   {{"t0"}, "x5"},   {{"t1"}, "x6"},    {{"t2"}, "x7"},
41      {{"s0"}, "x8"},   {{"s1"}, "x9"},   {{"a0"}, "x10"},   {{"a1"}, "x11"},
42      {{"a2"}, "x12"},  {{"a3"}, "x13"},  {{"a4"}, "x14"},   {{"a5"}, "x15"},
43      {{"a6"}, "x16"},  {{"a7"}, "x17"},  {{"s2"}, "x18"},   {{"s3"}, "x19"},
44      {{"s4"}, "x20"},  {{"s5"}, "x21"},  {{"s6"}, "x22"},   {{"s7"}, "x23"},
45      {{"s8"}, "x24"},  {{"s9"}, "x25"},  {{"s10"}, "x26"},  {{"s11"}, "x27"},
46      {{"t3"}, "x28"},  {{"t4"}, "x29"},  {{"t5"}, "x30"},   {{"t6"}, "x31"},
47      {{"ft0"}, "f0"},  {{"ft1"}, "f1"},  {{"ft2"}, "f2"},   {{"ft3"}, "f3"},
48      {{"ft4"}, "f4"},  {{"ft5"}, "f5"},  {{"ft6"}, "f6"},   {{"ft7"}, "f7"},
49      {{"fs0"}, "f8"},  {{"fs1"}, "f9"},  {{"fa0"}, "f10"},  {{"fa1"}, "f11"},
50      {{"fa2"}, "f12"}, {{"fa3"}, "f13"}, {{"fa4"}, "f14"},  {{"fa5"}, "f15"},
51      {{"fa6"}, "f16"}, {{"fa7"}, "f17"}, {{"fs2"}, "f18"},  {{"fs3"}, "f19"},
52      {{"fs4"}, "f20"}, {{"fs5"}, "f21"}, {{"fs6"}, "f22"},  {{"fs7"}, "f23"},
53      {{"fs8"}, "f24"}, {{"fs9"}, "f25"}, {{"fs10"}, "f26"}, {{"fs11"}, "f27"},
54      {{"ft8"}, "f28"}, {{"ft9"}, "f29"}, {{"ft10"}, "f30"}, {{"ft11"}, "f31"}};
55  return llvm::makeArrayRef(GCCRegAliases);
56}
57
58bool RISCVTargetInfo::validateAsmConstraint(
59    const char *&Name, TargetInfo::ConstraintInfo &Info) const {
60  switch (*Name) {
61  default:
62    return false;
63  case 'I':
64    // A 12-bit signed immediate.
65    Info.setRequiresImmediate(-2048, 2047);
66    return true;
67  case 'J':
68    // Integer zero.
69    Info.setRequiresImmediate(0);
70    return true;
71  case 'K':
72    // A 5-bit unsigned immediate for CSR access instructions.
73    Info.setRequiresImmediate(0, 31);
74    return true;
75  case 'f':
76    // A floating-point register.
77    Info.setAllowsRegister();
78    return true;
79  case 'A':
80    // An address that is held in a general-purpose register.
81    Info.setAllowsMemory();
82    return true;
83  }
84}
85
86void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
87                                       MacroBuilder &Builder) const {
88  Builder.defineMacro("__ELF__");
89  Builder.defineMacro("__riscv");
90  bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
91  Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32");
92  StringRef CodeModel = getTargetOpts().CodeModel;
93  if (CodeModel == "default")
94    CodeModel = "small";
95
96  if (CodeModel == "small")
97    Builder.defineMacro("__riscv_cmodel_medlow");
98  else if (CodeModel == "medium")
99    Builder.defineMacro("__riscv_cmodel_medany");
100
101  StringRef ABIName = getABI();
102  if (ABIName == "ilp32f" || ABIName == "lp64f")
103    Builder.defineMacro("__riscv_float_abi_single");
104  else if (ABIName == "ilp32d" || ABIName == "lp64d")
105    Builder.defineMacro("__riscv_float_abi_double");
106  else
107    Builder.defineMacro("__riscv_float_abi_soft");
108
109  if (ABIName == "ilp32e")
110    Builder.defineMacro("__riscv_abi_rve");
111
112  if (HasM) {
113    Builder.defineMacro("__riscv_mul");
114    Builder.defineMacro("__riscv_div");
115    Builder.defineMacro("__riscv_muldiv");
116  }
117
118  if (HasA) {
119    Builder.defineMacro("__riscv_atomic");
120    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
121    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
122    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
123    if (Is64Bit)
124      Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
125  }
126
127  if (HasF || HasD) {
128    Builder.defineMacro("__riscv_flen", HasD ? "64" : "32");
129    Builder.defineMacro("__riscv_fdiv");
130    Builder.defineMacro("__riscv_fsqrt");
131  }
132
133  if (HasC)
134    Builder.defineMacro("__riscv_compressed");
135
136  if (HasB)
137    Builder.defineMacro("__riscv_bitmanip");
138}
139
140/// Return true if has this feature, need to sync with handleTargetFeatures.
141bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
142  bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
143  return llvm::StringSwitch<bool>(Feature)
144      .Case("riscv", true)
145      .Case("riscv32", !Is64Bit)
146      .Case("riscv64", Is64Bit)
147      .Case("m", HasM)
148      .Case("a", HasA)
149      .Case("f", HasF)
150      .Case("d", HasD)
151      .Case("c", HasC)
152      .Case("experimental-b", HasB)
153      .Default(false);
154}
155
156/// Perform initialization based on the user configured set of features.
157bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
158                                           DiagnosticsEngine &Diags) {
159  for (const auto &Feature : Features) {
160    if (Feature == "+m")
161      HasM = true;
162    else if (Feature == "+a")
163      HasA = true;
164    else if (Feature == "+f")
165      HasF = true;
166    else if (Feature == "+d")
167      HasD = true;
168    else if (Feature == "+c")
169      HasC = true;
170    else if (Feature == "+experimental-b")
171      HasB = true;
172  }
173
174  return true;
175}
176
177bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const {
178  return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
179                                   /*Is64Bit=*/false);
180}
181
182void RISCV32TargetInfo::fillValidCPUList(
183    SmallVectorImpl<StringRef> &Values) const {
184  llvm::RISCV::fillValidCPUArchList(Values, false);
185}
186
187bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
188  return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
189                                   /*Is64Bit=*/true);
190}
191
192void RISCV64TargetInfo::fillValidCPUList(
193    SmallVectorImpl<StringRef> &Values) const {
194  llvm::RISCV::fillValidCPUArchList(Values, true);
195}
196