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("^") + std::string(Constraint, 2); 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 (HasZbr) 211 Builder.defineMacro("__riscv_zbr", "93000"); 212 213 if (HasZbs) 214 Builder.defineMacro("__riscv_zbs", "93000"); 215 216 if (HasZbt) 217 Builder.defineMacro("__riscv_zbt", "93000"); 218 219 if (HasZfh) 220 Builder.defineMacro("__riscv_zfh", "1000"); 221 222 if (HasZvamo) 223 Builder.defineMacro("__riscv_zvamo", "10000"); 224 225 if (HasZvlsseg) 226 Builder.defineMacro("__riscv_zvlsseg", "10000"); 227 } 228 229 const Builtin::Info RISCVTargetInfo::BuiltinInfo[] = { 230 #define BUILTIN(ID, TYPE, ATTRS) \ 231 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, 232 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ 233 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE}, 234 #include "clang/Basic/BuiltinsRISCV.def" 235 }; 236 237 ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const { 238 return llvm::makeArrayRef(BuiltinInfo, clang::RISCV::LastTSBuiltin - 239 Builtin::FirstTSBuiltin); 240 } 241 242 bool RISCVTargetInfo::initFeatureMap( 243 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, 244 const std::vector<std::string> &FeaturesVec) const { 245 246 if (getTriple().getArch() == llvm::Triple::riscv64) 247 Features["64bit"] = true; 248 249 return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); 250 } 251 252 /// Return true if has this feature, need to sync with handleTargetFeatures. 253 bool RISCVTargetInfo::hasFeature(StringRef Feature) const { 254 bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; 255 return llvm::StringSwitch<bool>(Feature) 256 .Case("riscv", true) 257 .Case("riscv32", !Is64Bit) 258 .Case("riscv64", Is64Bit) 259 .Case("64bit", Is64Bit) 260 .Case("m", HasM) 261 .Case("a", HasA) 262 .Case("f", HasF) 263 .Case("d", HasD) 264 .Case("c", HasC) 265 .Case("experimental-b", HasB) 266 .Case("experimental-v", HasV) 267 .Case("experimental-zba", HasZba) 268 .Case("experimental-zbb", HasZbb) 269 .Case("experimental-zbc", HasZbc) 270 .Case("experimental-zbe", HasZbe) 271 .Case("experimental-zbf", HasZbf) 272 .Case("experimental-zbm", HasZbm) 273 .Case("experimental-zbp", HasZbp) 274 .Case("experimental-zbr", HasZbr) 275 .Case("experimental-zbs", HasZbs) 276 .Case("experimental-zbt", HasZbt) 277 .Case("experimental-zfh", HasZfh) 278 .Case("experimental-zvamo", HasZvamo) 279 .Case("experimental-zvlsseg", HasZvlsseg) 280 .Default(false); 281 } 282 283 /// Perform initialization based on the user configured set of features. 284 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 285 DiagnosticsEngine &Diags) { 286 for (const auto &Feature : Features) { 287 if (Feature == "+m") 288 HasM = true; 289 else if (Feature == "+a") 290 HasA = true; 291 else if (Feature == "+f") 292 HasF = true; 293 else if (Feature == "+d") 294 HasD = true; 295 else if (Feature == "+c") 296 HasC = true; 297 else if (Feature == "+experimental-b") 298 HasB = true; 299 else if (Feature == "+experimental-v") 300 HasV = true; 301 else if (Feature == "+experimental-zba") 302 HasZba = true; 303 else if (Feature == "+experimental-zbb") 304 HasZbb = true; 305 else if (Feature == "+experimental-zbc") 306 HasZbc = true; 307 else if (Feature == "+experimental-zbe") 308 HasZbe = true; 309 else if (Feature == "+experimental-zbf") 310 HasZbf = true; 311 else if (Feature == "+experimental-zbm") 312 HasZbm = true; 313 else if (Feature == "+experimental-zbp") 314 HasZbp = true; 315 else if (Feature == "+experimental-zbr") 316 HasZbr = true; 317 else if (Feature == "+experimental-zbs") 318 HasZbs = true; 319 else if (Feature == "+experimental-zbt") 320 HasZbt = true; 321 else if (Feature == "+experimental-zfh") 322 HasZfh = true; 323 else if (Feature == "+experimental-zvamo") 324 HasZvamo = true; 325 else if (Feature == "+experimental-zvlsseg") 326 HasZvlsseg = true; 327 } 328 329 return true; 330 } 331 332 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const { 333 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), 334 /*Is64Bit=*/false); 335 } 336 337 void RISCV32TargetInfo::fillValidCPUList( 338 SmallVectorImpl<StringRef> &Values) const { 339 llvm::RISCV::fillValidCPUArchList(Values, false); 340 } 341 342 bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const { 343 return llvm::RISCV::checkTuneCPUKind( 344 llvm::RISCV::parseTuneCPUKind(Name, false), 345 /*Is64Bit=*/false); 346 } 347 348 void RISCV32TargetInfo::fillValidTuneCPUList( 349 SmallVectorImpl<StringRef> &Values) const { 350 llvm::RISCV::fillValidTuneCPUArchList(Values, false); 351 } 352 353 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const { 354 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), 355 /*Is64Bit=*/true); 356 } 357 358 void RISCV64TargetInfo::fillValidCPUList( 359 SmallVectorImpl<StringRef> &Values) const { 360 llvm::RISCV::fillValidCPUArchList(Values, true); 361 } 362 363 bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const { 364 return llvm::RISCV::checkTuneCPUKind( 365 llvm::RISCV::parseTuneCPUKind(Name, true), 366 /*Is64Bit=*/true); 367 } 368 369 void RISCV64TargetInfo::fillValidTuneCPUList( 370 SmallVectorImpl<StringRef> &Values) const { 371 llvm::RISCV::fillValidTuneCPUArchList(Values, true); 372 } 373