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