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 (HasV) { 180 Builder.defineMacro("__riscv_v", "10000"); 181 Builder.defineMacro("__riscv_vector"); 182 } 183 184 if (HasZba) 185 Builder.defineMacro("__riscv_zba", "1000000"); 186 187 if (HasZbb) 188 Builder.defineMacro("__riscv_zbb", "1000000"); 189 190 if (HasZbc) 191 Builder.defineMacro("__riscv_zbc", "1000000"); 192 193 if (HasZbe) 194 Builder.defineMacro("__riscv_zbe", "93000"); 195 196 if (HasZbf) 197 Builder.defineMacro("__riscv_zbf", "93000"); 198 199 if (HasZbm) 200 Builder.defineMacro("__riscv_zbm", "93000"); 201 202 if (HasZbp) 203 Builder.defineMacro("__riscv_zbp", "93000"); 204 205 if (HasZbr) 206 Builder.defineMacro("__riscv_zbr", "93000"); 207 208 if (HasZbs) 209 Builder.defineMacro("__riscv_zbs", "1000000"); 210 211 if (HasZbt) 212 Builder.defineMacro("__riscv_zbt", "93000"); 213 214 if (HasZfh) 215 Builder.defineMacro("__riscv_zfh", "1000"); 216 217 if (HasZvamo) 218 Builder.defineMacro("__riscv_zvamo", "10000"); 219 220 if (HasZvlsseg) 221 Builder.defineMacro("__riscv_zvlsseg", "10000"); 222 } 223 224 const Builtin::Info RISCVTargetInfo::BuiltinInfo[] = { 225 #define BUILTIN(ID, TYPE, ATTRS) \ 226 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, 227 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ 228 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE}, 229 #include "clang/Basic/BuiltinsRISCV.def" 230 }; 231 232 ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const { 233 return llvm::makeArrayRef(BuiltinInfo, clang::RISCV::LastTSBuiltin - 234 Builtin::FirstTSBuiltin); 235 } 236 237 bool RISCVTargetInfo::initFeatureMap( 238 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, 239 const std::vector<std::string> &FeaturesVec) const { 240 241 if (getTriple().getArch() == llvm::Triple::riscv64) 242 Features["64bit"] = true; 243 244 return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); 245 } 246 247 /// Return true if has this feature, need to sync with handleTargetFeatures. 248 bool RISCVTargetInfo::hasFeature(StringRef Feature) const { 249 bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; 250 return llvm::StringSwitch<bool>(Feature) 251 .Case("riscv", true) 252 .Case("riscv32", !Is64Bit) 253 .Case("riscv64", Is64Bit) 254 .Case("64bit", Is64Bit) 255 .Case("m", HasM) 256 .Case("a", HasA) 257 .Case("f", HasF) 258 .Case("d", HasD) 259 .Case("c", HasC) 260 .Case("experimental-v", HasV) 261 .Case("experimental-zba", HasZba) 262 .Case("experimental-zbb", HasZbb) 263 .Case("experimental-zbc", HasZbc) 264 .Case("experimental-zbe", HasZbe) 265 .Case("experimental-zbf", HasZbf) 266 .Case("experimental-zbm", HasZbm) 267 .Case("experimental-zbp", HasZbp) 268 .Case("experimental-zbr", HasZbr) 269 .Case("experimental-zbs", HasZbs) 270 .Case("experimental-zbt", HasZbt) 271 .Case("experimental-zfh", HasZfh) 272 .Case("experimental-zvamo", HasZvamo) 273 .Case("experimental-zvlsseg", HasZvlsseg) 274 .Default(false); 275 } 276 277 /// Perform initialization based on the user configured set of features. 278 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 279 DiagnosticsEngine &Diags) { 280 for (const auto &Feature : Features) { 281 if (Feature == "+m") 282 HasM = true; 283 else if (Feature == "+a") 284 HasA = true; 285 else if (Feature == "+f") 286 HasF = true; 287 else if (Feature == "+d") 288 HasD = true; 289 else if (Feature == "+c") 290 HasC = true; 291 else if (Feature == "+experimental-v") 292 HasV = true; 293 else if (Feature == "+experimental-zba") 294 HasZba = true; 295 else if (Feature == "+experimental-zbb") 296 HasZbb = true; 297 else if (Feature == "+experimental-zbc") 298 HasZbc = true; 299 else if (Feature == "+experimental-zbe") 300 HasZbe = true; 301 else if (Feature == "+experimental-zbf") 302 HasZbf = true; 303 else if (Feature == "+experimental-zbm") 304 HasZbm = true; 305 else if (Feature == "+experimental-zbp") 306 HasZbp = 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