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 19using namespace clang; 20using namespace clang::targets; 21 22ArrayRef<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 44ArrayRef<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 65bool 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 101std::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 115void 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 229const 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 237ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const { 238 return llvm::makeArrayRef(BuiltinInfo, clang::RISCV::LastTSBuiltin - 239 Builtin::FirstTSBuiltin); 240} 241 242bool 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. 253bool 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-zbproposedc", HasZbproposedc) 275 .Case("experimental-zbr", HasZbr) 276 .Case("experimental-zbs", HasZbs) 277 .Case("experimental-zbt", HasZbt) 278 .Case("experimental-zfh", HasZfh) 279 .Case("experimental-zvamo", HasZvamo) 280 .Case("experimental-zvlsseg", HasZvlsseg) 281 .Default(false); 282} 283 284/// Perform initialization based on the user configured set of features. 285bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 286 DiagnosticsEngine &Diags) { 287 for (const auto &Feature : Features) { 288 if (Feature == "+m") 289 HasM = true; 290 else if (Feature == "+a") 291 HasA = true; 292 else if (Feature == "+f") 293 HasF = true; 294 else if (Feature == "+d") 295 HasD = true; 296 else if (Feature == "+c") 297 HasC = true; 298 else if (Feature == "+experimental-b") 299 HasB = true; 300 else if (Feature == "+experimental-v") 301 HasV = true; 302 else if (Feature == "+experimental-zba") 303 HasZba = true; 304 else if (Feature == "+experimental-zbb") 305 HasZbb = true; 306 else if (Feature == "+experimental-zbc") 307 HasZbc = true; 308 else if (Feature == "+experimental-zbe") 309 HasZbe = true; 310 else if (Feature == "+experimental-zbf") 311 HasZbf = true; 312 else if (Feature == "+experimental-zbm") 313 HasZbm = true; 314 else if (Feature == "+experimental-zbp") 315 HasZbp = true; 316 else if (Feature == "+experimental-zbproposedc") 317 HasZbproposedc = true; 318 else if (Feature == "+experimental-zbr") 319 HasZbr = true; 320 else if (Feature == "+experimental-zbs") 321 HasZbs = true; 322 else if (Feature == "+experimental-zbt") 323 HasZbt = true; 324 else if (Feature == "+experimental-zfh") 325 HasZfh = true; 326 else if (Feature == "+experimental-zvamo") 327 HasZvamo = true; 328 else if (Feature == "+experimental-zvlsseg") 329 HasZvlsseg = true; 330 } 331 332 return true; 333} 334 335bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const { 336 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), 337 /*Is64Bit=*/false); 338} 339 340void RISCV32TargetInfo::fillValidCPUList( 341 SmallVectorImpl<StringRef> &Values) const { 342 llvm::RISCV::fillValidCPUArchList(Values, false); 343} 344 345bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const { 346 return llvm::RISCV::checkTuneCPUKind( 347 llvm::RISCV::parseTuneCPUKind(Name, false), 348 /*Is64Bit=*/false); 349} 350 351void RISCV32TargetInfo::fillValidTuneCPUList( 352 SmallVectorImpl<StringRef> &Values) const { 353 llvm::RISCV::fillValidTuneCPUArchList(Values, false); 354} 355 356bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const { 357 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), 358 /*Is64Bit=*/true); 359} 360 361void RISCV64TargetInfo::fillValidCPUList( 362 SmallVectorImpl<StringRef> &Values) const { 363 llvm::RISCV::fillValidCPUArchList(Values, true); 364} 365 366bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const { 367 return llvm::RISCV::checkTuneCPUKind( 368 llvm::RISCV::parseTuneCPUKind(Name, true), 369 /*Is64Bit=*/true); 370} 371 372void RISCV64TargetInfo::fillValidTuneCPUList( 373 SmallVectorImpl<StringRef> &Values) const { 374 llvm::RISCV::fillValidTuneCPUArchList(Values, true); 375} 376