xref: /freebsd/contrib/llvm-project/clang/lib/Basic/Targets/RISCV.cpp (revision c66ec88fed842fbaad62c30d510644ceb7bd2d71)
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 
18 using namespace clang;
19 using namespace clang::targets;
20 
21 ArrayRef<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 
37 ArrayRef<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 
58 bool 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 
86 void 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.
141 bool 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.
157 bool 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 
177 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const {
178   return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
179                                    /*Is64Bit=*/false);
180 }
181 
182 void RISCV32TargetInfo::fillValidCPUList(
183     SmallVectorImpl<StringRef> &Values) const {
184   llvm::RISCV::fillValidCPUArchList(Values, false);
185 }
186 
187 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
188   return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
189                                    /*Is64Bit=*/true);
190 }
191 
192 void RISCV64TargetInfo::fillValidCPUList(
193     SmallVectorImpl<StringRef> &Values) const {
194   llvm::RISCV::fillValidCPUArchList(Values, true);
195 }
196