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 'v': 91 // A vector register. 92 if (Name[1] == 'r' || Name[1] == 'm') { 93 Info.setAllowsRegister(); 94 Name += 1; 95 return true; 96 } 97 return false; 98 } 99 } 100 101 std::string RISCVTargetInfo::convertConstraint(const char *&Constraint) const { 102 std::string R; 103 switch (*Constraint) { 104 case 'v': 105 R = std::string("v"); 106 Constraint += 1; 107 break; 108 default: 109 R = TargetInfo::convertConstraint(Constraint); 110 break; 111 } 112 return R; 113 } 114 115 void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, 116 MacroBuilder &Builder) const { 117 Builder.defineMacro("__ELF__"); 118 Builder.defineMacro("__riscv"); 119 bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; 120 Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32"); 121 StringRef CodeModel = getTargetOpts().CodeModel; 122 if (CodeModel == "default") 123 CodeModel = "small"; 124 125 if (CodeModel == "small") 126 Builder.defineMacro("__riscv_cmodel_medlow"); 127 else if (CodeModel == "medium") 128 Builder.defineMacro("__riscv_cmodel_medany"); 129 130 StringRef ABIName = getABI(); 131 if (ABIName == "ilp32f" || ABIName == "lp64f") 132 Builder.defineMacro("__riscv_float_abi_single"); 133 else if (ABIName == "ilp32d" || ABIName == "lp64d") 134 Builder.defineMacro("__riscv_float_abi_double"); 135 else 136 Builder.defineMacro("__riscv_float_abi_soft"); 137 138 if (ABIName == "ilp32e") 139 Builder.defineMacro("__riscv_abi_rve"); 140 141 Builder.defineMacro("__riscv_arch_test"); 142 Builder.defineMacro("__riscv_i", "2000000"); 143 144 if (HasM) { 145 Builder.defineMacro("__riscv_m", "2000000"); 146 Builder.defineMacro("__riscv_mul"); 147 Builder.defineMacro("__riscv_div"); 148 Builder.defineMacro("__riscv_muldiv"); 149 } 150 151 if (HasA) { 152 Builder.defineMacro("__riscv_a", "2000000"); 153 Builder.defineMacro("__riscv_atomic"); 154 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); 155 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); 156 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); 157 if (Is64Bit) 158 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); 159 } 160 161 if (HasF || HasD) { 162 Builder.defineMacro("__riscv_f", "2000000"); 163 Builder.defineMacro("__riscv_flen", HasD ? "64" : "32"); 164 Builder.defineMacro("__riscv_fdiv"); 165 Builder.defineMacro("__riscv_fsqrt"); 166 } 167 168 if (HasD) 169 Builder.defineMacro("__riscv_d", "2000000"); 170 171 if (HasC) { 172 Builder.defineMacro("__riscv_c", "2000000"); 173 Builder.defineMacro("__riscv_compressed"); 174 } 175 176 if (HasB) { 177 Builder.defineMacro("__riscv_b", "93000"); 178 Builder.defineMacro("__riscv_bitmanip"); 179 } 180 181 if (HasV) { 182 Builder.defineMacro("__riscv_v", "10000"); 183 Builder.defineMacro("__riscv_vector"); 184 } 185 186 if (HasZba) 187 Builder.defineMacro("__riscv_zba", "93000"); 188 189 if (HasZbb) 190 Builder.defineMacro("__riscv_zbb", "93000"); 191 192 if (HasZbc) 193 Builder.defineMacro("__riscv_zbc", "93000"); 194 195 if (HasZbe) 196 Builder.defineMacro("__riscv_zbe", "93000"); 197 198 if (HasZbf) 199 Builder.defineMacro("__riscv_zbf", "93000"); 200 201 if (HasZbm) 202 Builder.defineMacro("__riscv_zbm", "93000"); 203 204 if (HasZbp) 205 Builder.defineMacro("__riscv_zbp", "93000"); 206 207 if (HasZbproposedc) 208 Builder.defineMacro("__riscv_zbproposedc", "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 /// Return true if has this feature, need to sync with handleTargetFeatures. 243 bool RISCVTargetInfo::hasFeature(StringRef Feature) const { 244 bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; 245 return llvm::StringSwitch<bool>(Feature) 246 .Case("riscv", true) 247 .Case("riscv32", !Is64Bit) 248 .Case("riscv64", Is64Bit) 249 .Case("m", HasM) 250 .Case("a", HasA) 251 .Case("f", HasF) 252 .Case("d", HasD) 253 .Case("c", HasC) 254 .Case("experimental-b", HasB) 255 .Case("experimental-v", HasV) 256 .Case("experimental-zba", HasZba) 257 .Case("experimental-zbb", HasZbb) 258 .Case("experimental-zbc", HasZbc) 259 .Case("experimental-zbe", HasZbe) 260 .Case("experimental-zbf", HasZbf) 261 .Case("experimental-zbm", HasZbm) 262 .Case("experimental-zbp", HasZbp) 263 .Case("experimental-zbproposedc", HasZbproposedc) 264 .Case("experimental-zbr", HasZbr) 265 .Case("experimental-zbs", HasZbs) 266 .Case("experimental-zbt", HasZbt) 267 .Case("experimental-zfh", HasZfh) 268 .Case("experimental-zvamo", HasZvamo) 269 .Case("experimental-zvlsseg", HasZvlsseg) 270 .Default(false); 271 } 272 273 /// Perform initialization based on the user configured set of features. 274 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 275 DiagnosticsEngine &Diags) { 276 for (const auto &Feature : Features) { 277 if (Feature == "+m") 278 HasM = true; 279 else if (Feature == "+a") 280 HasA = true; 281 else if (Feature == "+f") 282 HasF = true; 283 else if (Feature == "+d") 284 HasD = true; 285 else if (Feature == "+c") 286 HasC = true; 287 else if (Feature == "+experimental-b") 288 HasB = true; 289 else if (Feature == "+experimental-v") 290 HasV = true; 291 else if (Feature == "+experimental-zba") 292 HasZba = true; 293 else if (Feature == "+experimental-zbb") 294 HasZbb = true; 295 else if (Feature == "+experimental-zbc") 296 HasZbc = true; 297 else if (Feature == "+experimental-zbe") 298 HasZbe = true; 299 else if (Feature == "+experimental-zbf") 300 HasZbf = true; 301 else if (Feature == "+experimental-zbm") 302 HasZbm = true; 303 else if (Feature == "+experimental-zbp") 304 HasZbp = true; 305 else if (Feature == "+experimental-zbproposedc") 306 HasZbproposedc = true; 307 else if (Feature == "+experimental-zbr") 308 HasZbr = true; 309 else if (Feature == "+experimental-zbs") 310 HasZbs = true; 311 else if (Feature == "+experimental-zbt") 312 HasZbt = true; 313 else if (Feature == "+experimental-zfh") 314 HasZfh = true; 315 else if (Feature == "+experimental-zvamo") 316 HasZvamo = true; 317 else if (Feature == "+experimental-zvlsseg") 318 HasZvlsseg = true; 319 } 320 321 return true; 322 } 323 324 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const { 325 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), 326 /*Is64Bit=*/false); 327 } 328 329 void RISCV32TargetInfo::fillValidCPUList( 330 SmallVectorImpl<StringRef> &Values) const { 331 llvm::RISCV::fillValidCPUArchList(Values, false); 332 } 333 334 bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const { 335 return llvm::RISCV::checkTuneCPUKind( 336 llvm::RISCV::parseTuneCPUKind(Name, false), 337 /*Is64Bit=*/false); 338 } 339 340 void RISCV32TargetInfo::fillValidTuneCPUList( 341 SmallVectorImpl<StringRef> &Values) const { 342 llvm::RISCV::fillValidTuneCPUArchList(Values, false); 343 } 344 345 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const { 346 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), 347 /*Is64Bit=*/true); 348 } 349 350 void RISCV64TargetInfo::fillValidCPUList( 351 SmallVectorImpl<StringRef> &Values) const { 352 llvm::RISCV::fillValidCPUArchList(Values, true); 353 } 354 355 bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const { 356 return llvm::RISCV::checkTuneCPUKind( 357 llvm::RISCV::parseTuneCPUKind(Name, true), 358 /*Is64Bit=*/true); 359 } 360 361 void RISCV64TargetInfo::fillValidTuneCPUList( 362 SmallVectorImpl<StringRef> &Values) const { 363 llvm::RISCV::fillValidTuneCPUArchList(Values, true); 364 } 365