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