1 //===--- RISCV.cpp - Implement RISC-V 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 RISC-V TargetInfo objects. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "RISCV.h" 14 #include "clang/Basic/Diagnostic.h" 15 #include "clang/Basic/MacroBuilder.h" 16 #include "clang/Basic/TargetBuiltins.h" 17 #include "llvm/ADT/StringSwitch.h" 18 #include "llvm/Support/raw_ostream.h" 19 #include "llvm/TargetParser/RISCVTargetParser.h" 20 #include <optional> 21 22 using namespace clang; 23 using namespace clang::targets; 24 25 ArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const { 26 // clang-format off 27 static const char *const GCCRegNames[] = { 28 // Integer registers 29 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", 30 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", 31 "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", 32 "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", 33 34 // Floating point registers 35 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", 36 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", 37 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", 38 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", 39 40 // Vector registers 41 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", 42 "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", 43 "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", 44 "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", 45 46 // CSRs 47 "fflags", "frm", "vtype", "vl", "vxsat", "vxrm" 48 }; 49 // clang-format on 50 return llvm::ArrayRef(GCCRegNames); 51 } 52 53 ArrayRef<TargetInfo::GCCRegAlias> RISCVTargetInfo::getGCCRegAliases() const { 54 static const TargetInfo::GCCRegAlias GCCRegAliases[] = { 55 {{"zero"}, "x0"}, {{"ra"}, "x1"}, {{"sp"}, "x2"}, {{"gp"}, "x3"}, 56 {{"tp"}, "x4"}, {{"t0"}, "x5"}, {{"t1"}, "x6"}, {{"t2"}, "x7"}, 57 {{"s0"}, "x8"}, {{"s1"}, "x9"}, {{"a0"}, "x10"}, {{"a1"}, "x11"}, 58 {{"a2"}, "x12"}, {{"a3"}, "x13"}, {{"a4"}, "x14"}, {{"a5"}, "x15"}, 59 {{"a6"}, "x16"}, {{"a7"}, "x17"}, {{"s2"}, "x18"}, {{"s3"}, "x19"}, 60 {{"s4"}, "x20"}, {{"s5"}, "x21"}, {{"s6"}, "x22"}, {{"s7"}, "x23"}, 61 {{"s8"}, "x24"}, {{"s9"}, "x25"}, {{"s10"}, "x26"}, {{"s11"}, "x27"}, 62 {{"t3"}, "x28"}, {{"t4"}, "x29"}, {{"t5"}, "x30"}, {{"t6"}, "x31"}, 63 {{"ft0"}, "f0"}, {{"ft1"}, "f1"}, {{"ft2"}, "f2"}, {{"ft3"}, "f3"}, 64 {{"ft4"}, "f4"}, {{"ft5"}, "f5"}, {{"ft6"}, "f6"}, {{"ft7"}, "f7"}, 65 {{"fs0"}, "f8"}, {{"fs1"}, "f9"}, {{"fa0"}, "f10"}, {{"fa1"}, "f11"}, 66 {{"fa2"}, "f12"}, {{"fa3"}, "f13"}, {{"fa4"}, "f14"}, {{"fa5"}, "f15"}, 67 {{"fa6"}, "f16"}, {{"fa7"}, "f17"}, {{"fs2"}, "f18"}, {{"fs3"}, "f19"}, 68 {{"fs4"}, "f20"}, {{"fs5"}, "f21"}, {{"fs6"}, "f22"}, {{"fs7"}, "f23"}, 69 {{"fs8"}, "f24"}, {{"fs9"}, "f25"}, {{"fs10"}, "f26"}, {{"fs11"}, "f27"}, 70 {{"ft8"}, "f28"}, {{"ft9"}, "f29"}, {{"ft10"}, "f30"}, {{"ft11"}, "f31"}}; 71 return llvm::ArrayRef(GCCRegAliases); 72 } 73 74 bool RISCVTargetInfo::validateAsmConstraint( 75 const char *&Name, TargetInfo::ConstraintInfo &Info) const { 76 switch (*Name) { 77 default: 78 return false; 79 case 'I': 80 // A 12-bit signed immediate. 81 Info.setRequiresImmediate(-2048, 2047); 82 return true; 83 case 'J': 84 // Integer zero. 85 Info.setRequiresImmediate(0); 86 return true; 87 case 'K': 88 // A 5-bit unsigned immediate for CSR access instructions. 89 Info.setRequiresImmediate(0, 31); 90 return true; 91 case 'f': 92 // A floating-point register. 93 Info.setAllowsRegister(); 94 return true; 95 case 'A': 96 // An address that is held in a general-purpose register. 97 Info.setAllowsMemory(); 98 return true; 99 case 's': 100 case 'S': // A symbol or label reference with a constant offset 101 Info.setAllowsRegister(); 102 return true; 103 case 'v': 104 // A vector register. 105 if (Name[1] == 'r' || Name[1] == 'm') { 106 Info.setAllowsRegister(); 107 Name += 1; 108 return true; 109 } 110 return false; 111 } 112 } 113 114 std::string RISCVTargetInfo::convertConstraint(const char *&Constraint) const { 115 std::string R; 116 switch (*Constraint) { 117 case 'v': 118 R = std::string("^") + std::string(Constraint, 2); 119 Constraint += 1; 120 break; 121 default: 122 R = TargetInfo::convertConstraint(Constraint); 123 break; 124 } 125 return R; 126 } 127 128 static unsigned getVersionValue(unsigned MajorVersion, unsigned MinorVersion) { 129 return MajorVersion * 1000000 + MinorVersion * 1000; 130 } 131 132 void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, 133 MacroBuilder &Builder) const { 134 Builder.defineMacro("__riscv"); 135 bool Is64Bit = getTriple().isRISCV64(); 136 Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32"); 137 StringRef CodeModel = getTargetOpts().CodeModel; 138 unsigned FLen = ISAInfo->getFLen(); 139 unsigned MinVLen = ISAInfo->getMinVLen(); 140 unsigned MaxELen = ISAInfo->getMaxELen(); 141 unsigned MaxELenFp = ISAInfo->getMaxELenFp(); 142 if (CodeModel == "default") 143 CodeModel = "small"; 144 145 if (CodeModel == "small") 146 Builder.defineMacro("__riscv_cmodel_medlow"); 147 else if (CodeModel == "medium") 148 Builder.defineMacro("__riscv_cmodel_medany"); 149 150 StringRef ABIName = getABI(); 151 if (ABIName == "ilp32f" || ABIName == "lp64f") 152 Builder.defineMacro("__riscv_float_abi_single"); 153 else if (ABIName == "ilp32d" || ABIName == "lp64d") 154 Builder.defineMacro("__riscv_float_abi_double"); 155 else 156 Builder.defineMacro("__riscv_float_abi_soft"); 157 158 if (ABIName == "ilp32e" || ABIName == "lp64e") 159 Builder.defineMacro("__riscv_abi_rve"); 160 161 Builder.defineMacro("__riscv_arch_test"); 162 163 for (auto &Extension : ISAInfo->getExtensions()) { 164 auto ExtName = Extension.first; 165 auto ExtInfo = Extension.second; 166 167 Builder.defineMacro(Twine("__riscv_", ExtName), 168 Twine(getVersionValue(ExtInfo.Major, ExtInfo.Minor))); 169 } 170 171 if (ISAInfo->hasExtension("zmmul")) 172 Builder.defineMacro("__riscv_mul"); 173 174 if (ISAInfo->hasExtension("m")) { 175 Builder.defineMacro("__riscv_div"); 176 Builder.defineMacro("__riscv_muldiv"); 177 } 178 179 if (ISAInfo->hasExtension("a")) { 180 Builder.defineMacro("__riscv_atomic"); 181 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); 182 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); 183 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); 184 if (Is64Bit) 185 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); 186 } 187 188 if (FLen) { 189 Builder.defineMacro("__riscv_flen", Twine(FLen)); 190 Builder.defineMacro("__riscv_fdiv"); 191 Builder.defineMacro("__riscv_fsqrt"); 192 } 193 194 if (MinVLen) { 195 Builder.defineMacro("__riscv_v_min_vlen", Twine(MinVLen)); 196 Builder.defineMacro("__riscv_v_elen", Twine(MaxELen)); 197 Builder.defineMacro("__riscv_v_elen_fp", Twine(MaxELenFp)); 198 } 199 200 if (ISAInfo->hasExtension("c")) 201 Builder.defineMacro("__riscv_compressed"); 202 203 if (ISAInfo->hasExtension("zve32x")) { 204 Builder.defineMacro("__riscv_vector"); 205 // Currently we support the v0.12 RISC-V V intrinsics. 206 Builder.defineMacro("__riscv_v_intrinsic", Twine(getVersionValue(0, 12))); 207 } 208 209 auto VScale = getVScaleRange(Opts); 210 if (VScale && VScale->first && VScale->first == VScale->second) 211 Builder.defineMacro("__riscv_v_fixed_vlen", 212 Twine(VScale->first * llvm::RISCV::RVVBitsPerBlock)); 213 214 if (FastScalarUnalignedAccess) 215 Builder.defineMacro("__riscv_misaligned_fast"); 216 else 217 Builder.defineMacro("__riscv_misaligned_avoid"); 218 219 if (ISAInfo->hasExtension("e")) { 220 if (Is64Bit) 221 Builder.defineMacro("__riscv_64e"); 222 else 223 Builder.defineMacro("__riscv_32e"); 224 } 225 } 226 227 static constexpr Builtin::Info BuiltinInfo[] = { 228 #define BUILTIN(ID, TYPE, ATTRS) \ 229 {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, 230 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ 231 {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, 232 #include "clang/Basic/BuiltinsRISCVVector.def" 233 #define BUILTIN(ID, TYPE, ATTRS) \ 234 {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, 235 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ 236 {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, 237 #include "clang/Basic/BuiltinsRISCV.inc" 238 }; 239 240 ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const { 241 return llvm::ArrayRef(BuiltinInfo, 242 clang::RISCV::LastTSBuiltin - Builtin::FirstTSBuiltin); 243 } 244 245 bool RISCVTargetInfo::initFeatureMap( 246 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, 247 const std::vector<std::string> &FeaturesVec) const { 248 249 unsigned XLen = 32; 250 251 if (getTriple().isRISCV64()) { 252 Features["64bit"] = true; 253 XLen = 64; 254 } else { 255 Features["32bit"] = true; 256 } 257 258 // If a target attribute specified a full arch string, override all the ISA 259 // extension target features. 260 const auto I = llvm::find(FeaturesVec, "__RISCV_TargetAttrNeedOverride"); 261 if (I != FeaturesVec.end()) { 262 std::vector<std::string> OverrideFeatures(std::next(I), FeaturesVec.end()); 263 264 // Add back any non ISA extension features, e.g. +relax. 265 auto IsNonISAExtFeature = [](StringRef Feature) { 266 assert(Feature.size() > 1 && (Feature[0] == '+' || Feature[0] == '-')); 267 StringRef Ext = Feature.substr(1); // drop the +/- 268 return !llvm::RISCVISAInfo::isSupportedExtensionFeature(Ext); 269 }; 270 llvm::copy_if(llvm::make_range(FeaturesVec.begin(), I), 271 std::back_inserter(OverrideFeatures), IsNonISAExtFeature); 272 273 return TargetInfo::initFeatureMap(Features, Diags, CPU, OverrideFeatures); 274 } 275 276 // Otherwise, parse the features and add any implied extensions. 277 std::vector<std::string> AllFeatures = FeaturesVec; 278 auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, FeaturesVec); 279 if (!ParseResult) { 280 std::string Buffer; 281 llvm::raw_string_ostream OutputErrMsg(Buffer); 282 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) { 283 OutputErrMsg << ErrMsg.getMessage(); 284 }); 285 Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str(); 286 return false; 287 } 288 289 // Append all features, not just new ones, so we override any negatives. 290 llvm::append_range(AllFeatures, (*ParseResult)->toFeatures()); 291 return TargetInfo::initFeatureMap(Features, Diags, CPU, AllFeatures); 292 } 293 294 std::optional<std::pair<unsigned, unsigned>> 295 RISCVTargetInfo::getVScaleRange(const LangOptions &LangOpts) const { 296 // RISCV::RVVBitsPerBlock is 64. 297 unsigned VScaleMin = ISAInfo->getMinVLen() / llvm::RISCV::RVVBitsPerBlock; 298 299 if (LangOpts.VScaleMin || LangOpts.VScaleMax) { 300 // Treat Zvl*b as a lower bound on vscale. 301 VScaleMin = std::max(VScaleMin, LangOpts.VScaleMin); 302 unsigned VScaleMax = LangOpts.VScaleMax; 303 if (VScaleMax != 0 && VScaleMax < VScaleMin) 304 VScaleMax = VScaleMin; 305 return std::pair<unsigned, unsigned>(VScaleMin ? VScaleMin : 1, VScaleMax); 306 } 307 308 if (VScaleMin > 0) { 309 unsigned VScaleMax = ISAInfo->getMaxVLen() / llvm::RISCV::RVVBitsPerBlock; 310 return std::make_pair(VScaleMin, VScaleMax); 311 } 312 313 return std::nullopt; 314 } 315 316 /// Return true if has this feature, need to sync with handleTargetFeatures. 317 bool RISCVTargetInfo::hasFeature(StringRef Feature) const { 318 bool Is64Bit = getTriple().isRISCV64(); 319 auto Result = llvm::StringSwitch<std::optional<bool>>(Feature) 320 .Case("riscv", true) 321 .Case("riscv32", !Is64Bit) 322 .Case("riscv64", Is64Bit) 323 .Case("32bit", !Is64Bit) 324 .Case("64bit", Is64Bit) 325 .Case("experimental", HasExperimental) 326 .Default(std::nullopt); 327 if (Result) 328 return *Result; 329 330 return ISAInfo->hasExtension(Feature); 331 } 332 333 /// Perform initialization based on the user configured set of features. 334 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 335 DiagnosticsEngine &Diags) { 336 unsigned XLen = getTriple().isArch64Bit() ? 64 : 32; 337 auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, Features); 338 if (!ParseResult) { 339 std::string Buffer; 340 llvm::raw_string_ostream OutputErrMsg(Buffer); 341 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) { 342 OutputErrMsg << ErrMsg.getMessage(); 343 }); 344 Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str(); 345 return false; 346 } else { 347 ISAInfo = std::move(*ParseResult); 348 } 349 350 if (ABI.empty()) 351 ABI = ISAInfo->computeDefaultABI().str(); 352 353 if (ISAInfo->hasExtension("zfh") || ISAInfo->hasExtension("zhinx")) 354 HasLegalHalfType = true; 355 356 FastScalarUnalignedAccess = 357 llvm::is_contained(Features, "+unaligned-scalar-mem"); 358 359 if (llvm::is_contained(Features, "+experimental")) 360 HasExperimental = true; 361 362 if (ABI == "ilp32e" && ISAInfo->hasExtension("d")) { 363 Diags.Report(diag::err_invalid_feature_combination) 364 << "ILP32E cannot be used with the D ISA extension"; 365 return false; 366 } 367 return true; 368 } 369 370 bool RISCVTargetInfo::isValidCPUName(StringRef Name) const { 371 bool Is64Bit = getTriple().isArch64Bit(); 372 return llvm::RISCV::parseCPU(Name, Is64Bit); 373 } 374 375 void RISCVTargetInfo::fillValidCPUList( 376 SmallVectorImpl<StringRef> &Values) const { 377 bool Is64Bit = getTriple().isArch64Bit(); 378 llvm::RISCV::fillValidCPUArchList(Values, Is64Bit); 379 } 380 381 bool RISCVTargetInfo::isValidTuneCPUName(StringRef Name) const { 382 bool Is64Bit = getTriple().isArch64Bit(); 383 return llvm::RISCV::parseTuneCPU(Name, Is64Bit); 384 } 385 386 void RISCVTargetInfo::fillValidTuneCPUList( 387 SmallVectorImpl<StringRef> &Values) const { 388 bool Is64Bit = getTriple().isArch64Bit(); 389 llvm::RISCV::fillValidTuneCPUArchList(Values, Is64Bit); 390 } 391 392 static void handleFullArchString(StringRef FullArchStr, 393 std::vector<std::string> &Features) { 394 Features.push_back("__RISCV_TargetAttrNeedOverride"); 395 auto RII = llvm::RISCVISAInfo::parseArchString( 396 FullArchStr, /* EnableExperimentalExtension */ true); 397 if (llvm::errorToBool(RII.takeError())) { 398 // Forward the invalid FullArchStr. 399 Features.push_back("+" + FullArchStr.str()); 400 } else { 401 // Append a full list of features, including any negative extensions so that 402 // we override the CPU's features. 403 std::vector<std::string> FeatStrings = 404 (*RII)->toFeatures(/* AddAllExtensions */ true); 405 Features.insert(Features.end(), FeatStrings.begin(), FeatStrings.end()); 406 } 407 } 408 409 ParsedTargetAttr RISCVTargetInfo::parseTargetAttr(StringRef Features) const { 410 ParsedTargetAttr Ret; 411 if (Features == "default") 412 return Ret; 413 SmallVector<StringRef, 1> AttrFeatures; 414 Features.split(AttrFeatures, ";"); 415 bool FoundArch = false; 416 417 for (auto &Feature : AttrFeatures) { 418 Feature = Feature.trim(); 419 StringRef AttrString = Feature.split("=").second.trim(); 420 421 if (Feature.starts_with("arch=")) { 422 // Override last features 423 Ret.Features.clear(); 424 if (FoundArch) 425 Ret.Duplicate = "arch="; 426 FoundArch = true; 427 428 if (AttrString.starts_with("+")) { 429 // EXTENSION like arch=+v,+zbb 430 SmallVector<StringRef, 1> Exts; 431 AttrString.split(Exts, ","); 432 for (auto Ext : Exts) { 433 if (Ext.empty()) 434 continue; 435 436 StringRef ExtName = Ext.substr(1); 437 std::string TargetFeature = 438 llvm::RISCVISAInfo::getTargetFeatureForExtension(ExtName); 439 if (!TargetFeature.empty()) 440 Ret.Features.push_back(Ext.front() + TargetFeature); 441 else 442 Ret.Features.push_back(Ext.str()); 443 } 444 } else { 445 // full-arch-string like arch=rv64gcv 446 handleFullArchString(AttrString, Ret.Features); 447 } 448 } else if (Feature.starts_with("cpu=")) { 449 if (!Ret.CPU.empty()) 450 Ret.Duplicate = "cpu="; 451 452 Ret.CPU = AttrString; 453 454 if (!FoundArch) { 455 // Update Features with CPU's features 456 StringRef MarchFromCPU = llvm::RISCV::getMArchFromMcpu(Ret.CPU); 457 if (MarchFromCPU != "") { 458 Ret.Features.clear(); 459 handleFullArchString(MarchFromCPU, Ret.Features); 460 } 461 } 462 } else if (Feature.starts_with("tune=")) { 463 if (!Ret.Tune.empty()) 464 Ret.Duplicate = "tune="; 465 466 Ret.Tune = AttrString; 467 } 468 } 469 return Ret; 470 } 471 472 TargetInfo::CallingConvCheckResult 473 RISCVTargetInfo::checkCallingConvention(CallingConv CC) const { 474 switch (CC) { 475 default: 476 return CCCR_Warning; 477 case CC_C: 478 case CC_RISCVVectorCall: 479 return CCCR_OK; 480 } 481 } 482