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