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