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 "clang/Basic/TargetBuiltins.h" 16 #include "llvm/ADT/StringSwitch.h" 17 #include "llvm/Support/TargetParser.h" 18 19 using namespace clang; 20 using namespace clang::targets; 21 22 ArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const { 23 static const char *const GCCRegNames[] = { 24 // Integer registers 25 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", 26 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", 27 "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", 28 "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", 29 30 // Floating point registers 31 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", 32 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", 33 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", 34 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"}; 35 return llvm::makeArrayRef(GCCRegNames); 36 } 37 38 ArrayRef<TargetInfo::GCCRegAlias> RISCVTargetInfo::getGCCRegAliases() const { 39 static const TargetInfo::GCCRegAlias GCCRegAliases[] = { 40 {{"zero"}, "x0"}, {{"ra"}, "x1"}, {{"sp"}, "x2"}, {{"gp"}, "x3"}, 41 {{"tp"}, "x4"}, {{"t0"}, "x5"}, {{"t1"}, "x6"}, {{"t2"}, "x7"}, 42 {{"s0"}, "x8"}, {{"s1"}, "x9"}, {{"a0"}, "x10"}, {{"a1"}, "x11"}, 43 {{"a2"}, "x12"}, {{"a3"}, "x13"}, {{"a4"}, "x14"}, {{"a5"}, "x15"}, 44 {{"a6"}, "x16"}, {{"a7"}, "x17"}, {{"s2"}, "x18"}, {{"s3"}, "x19"}, 45 {{"s4"}, "x20"}, {{"s5"}, "x21"}, {{"s6"}, "x22"}, {{"s7"}, "x23"}, 46 {{"s8"}, "x24"}, {{"s9"}, "x25"}, {{"s10"}, "x26"}, {{"s11"}, "x27"}, 47 {{"t3"}, "x28"}, {{"t4"}, "x29"}, {{"t5"}, "x30"}, {{"t6"}, "x31"}, 48 {{"ft0"}, "f0"}, {{"ft1"}, "f1"}, {{"ft2"}, "f2"}, {{"ft3"}, "f3"}, 49 {{"ft4"}, "f4"}, {{"ft5"}, "f5"}, {{"ft6"}, "f6"}, {{"ft7"}, "f7"}, 50 {{"fs0"}, "f8"}, {{"fs1"}, "f9"}, {{"fa0"}, "f10"}, {{"fa1"}, "f11"}, 51 {{"fa2"}, "f12"}, {{"fa3"}, "f13"}, {{"fa4"}, "f14"}, {{"fa5"}, "f15"}, 52 {{"fa6"}, "f16"}, {{"fa7"}, "f17"}, {{"fs2"}, "f18"}, {{"fs3"}, "f19"}, 53 {{"fs4"}, "f20"}, {{"fs5"}, "f21"}, {{"fs6"}, "f22"}, {{"fs7"}, "f23"}, 54 {{"fs8"}, "f24"}, {{"fs9"}, "f25"}, {{"fs10"}, "f26"}, {{"fs11"}, "f27"}, 55 {{"ft8"}, "f28"}, {{"ft9"}, "f29"}, {{"ft10"}, "f30"}, {{"ft11"}, "f31"}}; 56 return llvm::makeArrayRef(GCCRegAliases); 57 } 58 59 bool RISCVTargetInfo::validateAsmConstraint( 60 const char *&Name, TargetInfo::ConstraintInfo &Info) const { 61 switch (*Name) { 62 default: 63 return false; 64 case 'I': 65 // A 12-bit signed immediate. 66 Info.setRequiresImmediate(-2048, 2047); 67 return true; 68 case 'J': 69 // Integer zero. 70 Info.setRequiresImmediate(0); 71 return true; 72 case 'K': 73 // A 5-bit unsigned immediate for CSR access instructions. 74 Info.setRequiresImmediate(0, 31); 75 return true; 76 case 'f': 77 // A floating-point register. 78 Info.setAllowsRegister(); 79 return true; 80 case 'A': 81 // An address that is held in a general-purpose register. 82 Info.setAllowsMemory(); 83 return true; 84 } 85 } 86 87 void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, 88 MacroBuilder &Builder) const { 89 Builder.defineMacro("__ELF__"); 90 Builder.defineMacro("__riscv"); 91 bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; 92 Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32"); 93 StringRef CodeModel = getTargetOpts().CodeModel; 94 if (CodeModel == "default") 95 CodeModel = "small"; 96 97 if (CodeModel == "small") 98 Builder.defineMacro("__riscv_cmodel_medlow"); 99 else if (CodeModel == "medium") 100 Builder.defineMacro("__riscv_cmodel_medany"); 101 102 StringRef ABIName = getABI(); 103 if (ABIName == "ilp32f" || ABIName == "lp64f") 104 Builder.defineMacro("__riscv_float_abi_single"); 105 else if (ABIName == "ilp32d" || ABIName == "lp64d") 106 Builder.defineMacro("__riscv_float_abi_double"); 107 else 108 Builder.defineMacro("__riscv_float_abi_soft"); 109 110 if (ABIName == "ilp32e") 111 Builder.defineMacro("__riscv_abi_rve"); 112 113 Builder.defineMacro("__riscv_arch_test"); 114 Builder.defineMacro("__riscv_i", "2000000"); 115 116 if (HasM) { 117 Builder.defineMacro("__riscv_m", "2000000"); 118 Builder.defineMacro("__riscv_mul"); 119 Builder.defineMacro("__riscv_div"); 120 Builder.defineMacro("__riscv_muldiv"); 121 } 122 123 if (HasA) { 124 Builder.defineMacro("__riscv_a", "2000000"); 125 Builder.defineMacro("__riscv_atomic"); 126 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); 127 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); 128 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); 129 if (Is64Bit) 130 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); 131 } 132 133 if (HasF || HasD) { 134 Builder.defineMacro("__riscv_f", "2000000"); 135 Builder.defineMacro("__riscv_flen", HasD ? "64" : "32"); 136 Builder.defineMacro("__riscv_fdiv"); 137 Builder.defineMacro("__riscv_fsqrt"); 138 } 139 140 if (HasD) 141 Builder.defineMacro("__riscv_d", "2000000"); 142 143 if (HasC) { 144 Builder.defineMacro("__riscv_c", "2000000"); 145 Builder.defineMacro("__riscv_compressed"); 146 } 147 148 if (HasB) { 149 Builder.defineMacro("__riscv_b", "93000"); 150 Builder.defineMacro("__riscv_bitmanip"); 151 } 152 153 if (HasV) { 154 Builder.defineMacro("__riscv_v", "10000"); 155 Builder.defineMacro("__riscv_vector"); 156 } 157 158 if (HasZba) 159 Builder.defineMacro("__riscv_zba", "93000"); 160 161 if (HasZbb) 162 Builder.defineMacro("__riscv_zbb", "93000"); 163 164 if (HasZbc) 165 Builder.defineMacro("__riscv_zbc", "93000"); 166 167 if (HasZbe) 168 Builder.defineMacro("__riscv_zbe", "93000"); 169 170 if (HasZbf) 171 Builder.defineMacro("__riscv_zbf", "93000"); 172 173 if (HasZbm) 174 Builder.defineMacro("__riscv_zbm", "93000"); 175 176 if (HasZbp) 177 Builder.defineMacro("__riscv_zbp", "93000"); 178 179 if (HasZbproposedc) 180 Builder.defineMacro("__riscv_zbproposedc", "93000"); 181 182 if (HasZbr) 183 Builder.defineMacro("__riscv_zbr", "93000"); 184 185 if (HasZbs) 186 Builder.defineMacro("__riscv_zbs", "93000"); 187 188 if (HasZbt) 189 Builder.defineMacro("__riscv_zbt", "93000"); 190 191 if (HasZfh) 192 Builder.defineMacro("__riscv_zfh", "1000"); 193 194 if (HasZvamo) 195 Builder.defineMacro("__riscv_zvamo", "10000"); 196 197 if (HasZvlsseg) 198 Builder.defineMacro("__riscv_zvlsseg", "10000"); 199 } 200 201 const Builtin::Info RISCVTargetInfo::BuiltinInfo[] = { 202 #define BUILTIN(ID, TYPE, ATTRS) \ 203 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, 204 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ 205 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE}, 206 #include "clang/Basic/BuiltinsRISCV.def" 207 }; 208 209 ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const { 210 return llvm::makeArrayRef(BuiltinInfo, clang::RISCV::LastTSBuiltin - 211 Builtin::FirstTSBuiltin); 212 } 213 214 /// Return true if has this feature, need to sync with handleTargetFeatures. 215 bool RISCVTargetInfo::hasFeature(StringRef Feature) const { 216 bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; 217 return llvm::StringSwitch<bool>(Feature) 218 .Case("riscv", true) 219 .Case("riscv32", !Is64Bit) 220 .Case("riscv64", Is64Bit) 221 .Case("m", HasM) 222 .Case("a", HasA) 223 .Case("f", HasF) 224 .Case("d", HasD) 225 .Case("c", HasC) 226 .Case("experimental-b", HasB) 227 .Case("experimental-v", HasV) 228 .Case("experimental-zba", HasZba) 229 .Case("experimental-zbb", HasZbb) 230 .Case("experimental-zbc", HasZbc) 231 .Case("experimental-zbe", HasZbe) 232 .Case("experimental-zbf", HasZbf) 233 .Case("experimental-zbm", HasZbm) 234 .Case("experimental-zbp", HasZbp) 235 .Case("experimental-zbproposedc", HasZbproposedc) 236 .Case("experimental-zbr", HasZbr) 237 .Case("experimental-zbs", HasZbs) 238 .Case("experimental-zbt", HasZbt) 239 .Case("experimental-zfh", HasZfh) 240 .Case("experimental-zvamo", HasZvamo) 241 .Case("experimental-zvlsseg", HasZvlsseg) 242 .Default(false); 243 } 244 245 /// Perform initialization based on the user configured set of features. 246 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 247 DiagnosticsEngine &Diags) { 248 for (const auto &Feature : Features) { 249 if (Feature == "+m") 250 HasM = true; 251 else if (Feature == "+a") 252 HasA = true; 253 else if (Feature == "+f") 254 HasF = true; 255 else if (Feature == "+d") 256 HasD = true; 257 else if (Feature == "+c") 258 HasC = true; 259 else if (Feature == "+experimental-b") 260 HasB = true; 261 else if (Feature == "+experimental-v") 262 HasV = true; 263 else if (Feature == "+experimental-zba") 264 HasZba = true; 265 else if (Feature == "+experimental-zbb") 266 HasZbb = true; 267 else if (Feature == "+experimental-zbc") 268 HasZbc = true; 269 else if (Feature == "+experimental-zbe") 270 HasZbe = true; 271 else if (Feature == "+experimental-zbf") 272 HasZbf = true; 273 else if (Feature == "+experimental-zbm") 274 HasZbm = true; 275 else if (Feature == "+experimental-zbp") 276 HasZbp = true; 277 else if (Feature == "+experimental-zbproposedc") 278 HasZbproposedc = true; 279 else if (Feature == "+experimental-zbr") 280 HasZbr = true; 281 else if (Feature == "+experimental-zbs") 282 HasZbs = true; 283 else if (Feature == "+experimental-zbt") 284 HasZbt = true; 285 else if (Feature == "+experimental-zfh") 286 HasZfh = true; 287 else if (Feature == "+experimental-zvamo") 288 HasZvamo = true; 289 else if (Feature == "+experimental-zvlsseg") 290 HasZvlsseg = true; 291 } 292 293 return true; 294 } 295 296 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const { 297 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), 298 /*Is64Bit=*/false); 299 } 300 301 void RISCV32TargetInfo::fillValidCPUList( 302 SmallVectorImpl<StringRef> &Values) const { 303 llvm::RISCV::fillValidCPUArchList(Values, false); 304 } 305 306 bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const { 307 return llvm::RISCV::checkTuneCPUKind( 308 llvm::RISCV::parseTuneCPUKind(Name, false), 309 /*Is64Bit=*/false); 310 } 311 312 void RISCV32TargetInfo::fillValidTuneCPUList( 313 SmallVectorImpl<StringRef> &Values) const { 314 llvm::RISCV::fillValidTuneCPUArchList(Values, false); 315 } 316 317 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const { 318 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), 319 /*Is64Bit=*/true); 320 } 321 322 void RISCV64TargetInfo::fillValidCPUList( 323 SmallVectorImpl<StringRef> &Values) const { 324 llvm::RISCV::fillValidCPUArchList(Values, true); 325 } 326 327 bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const { 328 return llvm::RISCV::checkTuneCPUKind( 329 llvm::RISCV::parseTuneCPUKind(Name, true), 330 /*Is64Bit=*/true); 331 } 332 333 void RISCV64TargetInfo::fillValidTuneCPUList( 334 SmallVectorImpl<StringRef> &Values) const { 335 llvm::RISCV::fillValidTuneCPUArchList(Values, true); 336 } 337