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
getGCCRegNames() const21 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
getGCCRegAliases() const37 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
validateAsmConstraint(const char * & Name,TargetInfo::ConstraintInfo & Info) const58 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
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const86 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 if (HasV)
140 Builder.defineMacro("__riscv_vector");
141
142 if (HasZfh)
143 Builder.defineMacro("__riscv_zfh");
144 }
145
146 /// Return true if has this feature, need to sync with handleTargetFeatures.
hasFeature(StringRef Feature) const147 bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
148 bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
149 return llvm::StringSwitch<bool>(Feature)
150 .Case("riscv", true)
151 .Case("riscv32", !Is64Bit)
152 .Case("riscv64", Is64Bit)
153 .Case("m", HasM)
154 .Case("a", HasA)
155 .Case("f", HasF)
156 .Case("d", HasD)
157 .Case("c", HasC)
158 .Case("experimental-b", HasB)
159 .Case("experimental-v", HasV)
160 .Case("experimental-zfh", HasZfh)
161 .Default(false);
162 }
163
164 /// Perform initialization based on the user configured set of features.
handleTargetFeatures(std::vector<std::string> & Features,DiagnosticsEngine & Diags)165 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
166 DiagnosticsEngine &Diags) {
167 for (const auto &Feature : Features) {
168 if (Feature == "+m")
169 HasM = true;
170 else if (Feature == "+a")
171 HasA = true;
172 else if (Feature == "+f")
173 HasF = true;
174 else if (Feature == "+d")
175 HasD = true;
176 else if (Feature == "+c")
177 HasC = true;
178 else if (Feature == "+experimental-b")
179 HasB = true;
180 else if (Feature == "+experimental-v")
181 HasV = true;
182 else if (Feature == "+experimental-zfh")
183 HasZfh = true;
184 }
185
186 return true;
187 }
188
isValidCPUName(StringRef Name) const189 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const {
190 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
191 /*Is64Bit=*/false);
192 }
193
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const194 void RISCV32TargetInfo::fillValidCPUList(
195 SmallVectorImpl<StringRef> &Values) const {
196 llvm::RISCV::fillValidCPUArchList(Values, false);
197 }
198
isValidTuneCPUName(StringRef Name) const199 bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const {
200 return llvm::RISCV::checkTuneCPUKind(
201 llvm::RISCV::parseTuneCPUKind(Name, false),
202 /*Is64Bit=*/false);
203 }
204
fillValidTuneCPUList(SmallVectorImpl<StringRef> & Values) const205 void RISCV32TargetInfo::fillValidTuneCPUList(
206 SmallVectorImpl<StringRef> &Values) const {
207 llvm::RISCV::fillValidTuneCPUArchList(Values, false);
208 }
209
isValidCPUName(StringRef Name) const210 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
211 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
212 /*Is64Bit=*/true);
213 }
214
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const215 void RISCV64TargetInfo::fillValidCPUList(
216 SmallVectorImpl<StringRef> &Values) const {
217 llvm::RISCV::fillValidCPUArchList(Values, true);
218 }
219
isValidTuneCPUName(StringRef Name) const220 bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const {
221 return llvm::RISCV::checkTuneCPUKind(
222 llvm::RISCV::parseTuneCPUKind(Name, true),
223 /*Is64Bit=*/true);
224 }
225
fillValidTuneCPUList(SmallVectorImpl<StringRef> & Values) const226 void RISCV64TargetInfo::fillValidTuneCPUList(
227 SmallVectorImpl<StringRef> &Values) const {
228 llvm::RISCV::fillValidTuneCPUArchList(Values, true);
229 }
230