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