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   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 
120   if (HasF || HasD) {
121     Builder.defineMacro("__riscv_flen", HasD ? "64" : "32");
122     Builder.defineMacro("__riscv_fdiv");
123     Builder.defineMacro("__riscv_fsqrt");
124   }
125 
126   if (HasC)
127     Builder.defineMacro("__riscv_compressed");
128 
129   if (HasB) {
130     Builder.defineMacro("__riscv_bitmanip");
131   }
132 }
133 
134 /// Return true if has this feature, need to sync with handleTargetFeatures.
135 bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
136   bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
137   return llvm::StringSwitch<bool>(Feature)
138       .Case("riscv", true)
139       .Case("riscv32", !Is64Bit)
140       .Case("riscv64", Is64Bit)
141       .Case("m", HasM)
142       .Case("a", HasA)
143       .Case("f", HasF)
144       .Case("d", HasD)
145       .Case("c", HasC)
146       .Case("b", HasB)
147       .Default(false);
148 }
149 
150 /// Perform initialization based on the user configured set of features.
151 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
152                                            DiagnosticsEngine &Diags) {
153   for (const auto &Feature : Features) {
154     if (Feature == "+m")
155       HasM = true;
156     else if (Feature == "+a")
157       HasA = true;
158     else if (Feature == "+f")
159       HasF = true;
160     else if (Feature == "+d")
161       HasD = true;
162     else if (Feature == "+c")
163       HasC = true;
164     else if (Feature == "+b")
165       HasB = true;
166   }
167 
168   return true;
169 }
170