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 
17 using namespace clang;
18 using namespace clang::targets;
19 
20 ArrayRef<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 
36 ArrayRef<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 
57 bool 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 
85 void 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   // TODO: modify when more code models are supported.
92   Builder.defineMacro("__riscv_cmodel_medlow");
93 
94   StringRef ABIName = getABI();
95   if (ABIName == "ilp32f" || ABIName == "lp64f")
96     Builder.defineMacro("__riscv_float_abi_single");
97   else if (ABIName == "ilp32d" || ABIName == "lp64d")
98     Builder.defineMacro("__riscv_float_abi_double");
99   else if (ABIName == "ilp32e")
100     Builder.defineMacro("__riscv_abi_rve");
101   else
102     Builder.defineMacro("__riscv_float_abi_soft");
103 
104   if (HasM) {
105     Builder.defineMacro("__riscv_mul");
106     Builder.defineMacro("__riscv_div");
107     Builder.defineMacro("__riscv_muldiv");
108   }
109 
110   if (HasA)
111     Builder.defineMacro("__riscv_atomic");
112 
113   if (HasF || HasD) {
114     Builder.defineMacro("__riscv_flen", HasD ? "64" : "32");
115     Builder.defineMacro("__riscv_fdiv");
116     Builder.defineMacro("__riscv_fsqrt");
117   }
118 
119   if (HasC)
120     Builder.defineMacro("__riscv_compressed");
121 }
122 
123 /// Return true if has this feature, need to sync with handleTargetFeatures.
124 bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
125   bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
126   return llvm::StringSwitch<bool>(Feature)
127       .Case("riscv", true)
128       .Case("riscv32", !Is64Bit)
129       .Case("riscv64", Is64Bit)
130       .Case("m", HasM)
131       .Case("a", HasA)
132       .Case("f", HasF)
133       .Case("d", HasD)
134       .Case("c", HasC)
135       .Default(false);
136 }
137 
138 /// Perform initialization based on the user configured set of features.
139 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
140                                            DiagnosticsEngine &Diags) {
141   for (const auto &Feature : Features) {
142     if (Feature == "+m")
143       HasM = true;
144     else if (Feature == "+a")
145       HasA = true;
146     else if (Feature == "+f")
147       HasF = true;
148     else if (Feature == "+d")
149       HasD = true;
150     else if (Feature == "+c")
151       HasC = true;
152   }
153 
154   return true;
155 }
156