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/Diagnostic.h" 15 #include "clang/Basic/MacroBuilder.h" 16 #include "clang/Basic/TargetBuiltins.h" 17 #include "llvm/ADT/StringSwitch.h" 18 #include "llvm/Support/TargetParser.h" 19 #include "llvm/Support/raw_ostream.h" 20 21 using namespace clang; 22 using namespace clang::targets; 23 24 ArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const { 25 static const char *const GCCRegNames[] = { 26 // Integer registers 27 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", 28 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", 29 "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", 30 "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", 31 32 // Floating point registers 33 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", 34 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", 35 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", 36 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", 37 38 // Vector registers 39 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", 40 "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", 41 "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", 42 "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"}; 43 return llvm::makeArrayRef(GCCRegNames); 44 } 45 46 ArrayRef<TargetInfo::GCCRegAlias> RISCVTargetInfo::getGCCRegAliases() const { 47 static const TargetInfo::GCCRegAlias GCCRegAliases[] = { 48 {{"zero"}, "x0"}, {{"ra"}, "x1"}, {{"sp"}, "x2"}, {{"gp"}, "x3"}, 49 {{"tp"}, "x4"}, {{"t0"}, "x5"}, {{"t1"}, "x6"}, {{"t2"}, "x7"}, 50 {{"s0"}, "x8"}, {{"s1"}, "x9"}, {{"a0"}, "x10"}, {{"a1"}, "x11"}, 51 {{"a2"}, "x12"}, {{"a3"}, "x13"}, {{"a4"}, "x14"}, {{"a5"}, "x15"}, 52 {{"a6"}, "x16"}, {{"a7"}, "x17"}, {{"s2"}, "x18"}, {{"s3"}, "x19"}, 53 {{"s4"}, "x20"}, {{"s5"}, "x21"}, {{"s6"}, "x22"}, {{"s7"}, "x23"}, 54 {{"s8"}, "x24"}, {{"s9"}, "x25"}, {{"s10"}, "x26"}, {{"s11"}, "x27"}, 55 {{"t3"}, "x28"}, {{"t4"}, "x29"}, {{"t5"}, "x30"}, {{"t6"}, "x31"}, 56 {{"ft0"}, "f0"}, {{"ft1"}, "f1"}, {{"ft2"}, "f2"}, {{"ft3"}, "f3"}, 57 {{"ft4"}, "f4"}, {{"ft5"}, "f5"}, {{"ft6"}, "f6"}, {{"ft7"}, "f7"}, 58 {{"fs0"}, "f8"}, {{"fs1"}, "f9"}, {{"fa0"}, "f10"}, {{"fa1"}, "f11"}, 59 {{"fa2"}, "f12"}, {{"fa3"}, "f13"}, {{"fa4"}, "f14"}, {{"fa5"}, "f15"}, 60 {{"fa6"}, "f16"}, {{"fa7"}, "f17"}, {{"fs2"}, "f18"}, {{"fs3"}, "f19"}, 61 {{"fs4"}, "f20"}, {{"fs5"}, "f21"}, {{"fs6"}, "f22"}, {{"fs7"}, "f23"}, 62 {{"fs8"}, "f24"}, {{"fs9"}, "f25"}, {{"fs10"}, "f26"}, {{"fs11"}, "f27"}, 63 {{"ft8"}, "f28"}, {{"ft9"}, "f29"}, {{"ft10"}, "f30"}, {{"ft11"}, "f31"}}; 64 return llvm::makeArrayRef(GCCRegAliases); 65 } 66 67 bool RISCVTargetInfo::validateAsmConstraint( 68 const char *&Name, TargetInfo::ConstraintInfo &Info) const { 69 switch (*Name) { 70 default: 71 return false; 72 case 'I': 73 // A 12-bit signed immediate. 74 Info.setRequiresImmediate(-2048, 2047); 75 return true; 76 case 'J': 77 // Integer zero. 78 Info.setRequiresImmediate(0); 79 return true; 80 case 'K': 81 // A 5-bit unsigned immediate for CSR access instructions. 82 Info.setRequiresImmediate(0, 31); 83 return true; 84 case 'f': 85 // A floating-point register. 86 Info.setAllowsRegister(); 87 return true; 88 case 'A': 89 // An address that is held in a general-purpose register. 90 Info.setAllowsMemory(); 91 return true; 92 case 'S': // A symbolic address 93 Info.setAllowsRegister(); 94 return true; 95 case 'v': 96 // A vector register. 97 if (Name[1] == 'r' || Name[1] == 'm') { 98 Info.setAllowsRegister(); 99 Name += 1; 100 return true; 101 } 102 return false; 103 } 104 } 105 106 std::string RISCVTargetInfo::convertConstraint(const char *&Constraint) const { 107 std::string R; 108 switch (*Constraint) { 109 case 'v': 110 R = std::string("^") + std::string(Constraint, 2); 111 Constraint += 1; 112 break; 113 default: 114 R = TargetInfo::convertConstraint(Constraint); 115 break; 116 } 117 return R; 118 } 119 120 void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, 121 MacroBuilder &Builder) const { 122 Builder.defineMacro("__ELF__"); 123 Builder.defineMacro("__riscv"); 124 bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; 125 Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32"); 126 StringRef CodeModel = getTargetOpts().CodeModel; 127 unsigned FLen = ISAInfo->getFLen(); 128 unsigned MinVLen = ISAInfo->getMinVLen(); 129 unsigned MaxELen = ISAInfo->getMaxELen(); 130 unsigned MaxELenFp = ISAInfo->getMaxELenFp(); 131 if (CodeModel == "default") 132 CodeModel = "small"; 133 134 if (CodeModel == "small") 135 Builder.defineMacro("__riscv_cmodel_medlow"); 136 else if (CodeModel == "medium") 137 Builder.defineMacro("__riscv_cmodel_medany"); 138 139 StringRef ABIName = getABI(); 140 if (ABIName == "ilp32f" || ABIName == "lp64f") 141 Builder.defineMacro("__riscv_float_abi_single"); 142 else if (ABIName == "ilp32d" || ABIName == "lp64d") 143 Builder.defineMacro("__riscv_float_abi_double"); 144 else 145 Builder.defineMacro("__riscv_float_abi_soft"); 146 147 if (ABIName == "ilp32e") 148 Builder.defineMacro("__riscv_abi_rve"); 149 150 Builder.defineMacro("__riscv_arch_test"); 151 152 for (auto &Extension : ISAInfo->getExtensions()) { 153 auto ExtName = Extension.first; 154 auto ExtInfo = Extension.second; 155 unsigned Version = 156 (ExtInfo.MajorVersion * 1000000) + (ExtInfo.MinorVersion * 1000); 157 158 Builder.defineMacro(Twine("__riscv_", ExtName), Twine(Version)); 159 } 160 161 if (ISAInfo->hasExtension("m")) { 162 Builder.defineMacro("__riscv_mul"); 163 Builder.defineMacro("__riscv_div"); 164 Builder.defineMacro("__riscv_muldiv"); 165 } 166 167 if (ISAInfo->hasExtension("a")) { 168 Builder.defineMacro("__riscv_atomic"); 169 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); 170 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); 171 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); 172 if (Is64Bit) 173 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); 174 } 175 176 if (FLen) { 177 Builder.defineMacro("__riscv_flen", Twine(FLen)); 178 Builder.defineMacro("__riscv_fdiv"); 179 Builder.defineMacro("__riscv_fsqrt"); 180 } 181 182 if (MinVLen) { 183 Builder.defineMacro("__riscv_v_min_vlen", Twine(MinVLen)); 184 Builder.defineMacro("__riscv_v_elen", Twine(MaxELen)); 185 Builder.defineMacro("__riscv_v_elen_fp", Twine(MaxELenFp)); 186 } 187 188 if (ISAInfo->hasExtension("c")) 189 Builder.defineMacro("__riscv_compressed"); 190 191 if (ISAInfo->hasExtension("zve32x") || ISAInfo->hasExtension("v")) 192 Builder.defineMacro("__riscv_vector"); 193 } 194 195 const Builtin::Info RISCVTargetInfo::BuiltinInfo[] = { 196 #define BUILTIN(ID, TYPE, ATTRS) \ 197 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, 198 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ 199 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE}, 200 #include "clang/Basic/BuiltinsRISCVVector.def" 201 #define BUILTIN(ID, TYPE, ATTRS) \ 202 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, 203 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ 204 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE}, 205 #include "clang/Basic/BuiltinsRISCV.def" 206 }; 207 208 ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const { 209 return llvm::makeArrayRef(BuiltinInfo, clang::RISCV::LastTSBuiltin - 210 Builtin::FirstTSBuiltin); 211 } 212 213 bool RISCVTargetInfo::initFeatureMap( 214 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, 215 const std::vector<std::string> &FeaturesVec) const { 216 217 unsigned XLen = 32; 218 219 if (getTriple().getArch() == llvm::Triple::riscv64) { 220 Features["64bit"] = true; 221 XLen = 64; 222 } 223 224 auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, FeaturesVec); 225 if (!ParseResult) { 226 std::string Buffer; 227 llvm::raw_string_ostream OutputErrMsg(Buffer); 228 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) { 229 OutputErrMsg << ErrMsg.getMessage(); 230 }); 231 Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str(); 232 return false; 233 } 234 235 return TargetInfo::initFeatureMap(Features, Diags, CPU, 236 (*ParseResult)->toFeatureVector()); 237 } 238 239 /// Return true if has this feature, need to sync with handleTargetFeatures. 240 bool RISCVTargetInfo::hasFeature(StringRef Feature) const { 241 bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; 242 auto Result = llvm::StringSwitch<Optional<bool>>(Feature) 243 .Case("riscv", true) 244 .Case("riscv32", !Is64Bit) 245 .Case("riscv64", Is64Bit) 246 .Case("64bit", Is64Bit) 247 .Default(None); 248 if (Result.hasValue()) 249 return Result.getValue(); 250 251 if (ISAInfo->isSupportedExtensionFeature(Feature)) 252 return ISAInfo->hasExtension(Feature); 253 254 return false; 255 } 256 257 /// Perform initialization based on the user configured set of features. 258 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 259 DiagnosticsEngine &Diags) { 260 unsigned XLen = getTriple().isArch64Bit() ? 64 : 32; 261 auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, Features); 262 if (!ParseResult) { 263 std::string Buffer; 264 llvm::raw_string_ostream OutputErrMsg(Buffer); 265 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) { 266 OutputErrMsg << ErrMsg.getMessage(); 267 }); 268 Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str(); 269 return false; 270 } else { 271 ISAInfo = std::move(*ParseResult); 272 } 273 274 if (ABI.empty()) 275 ABI = llvm::RISCV::computeDefaultABIFromArch(*ISAInfo).str(); 276 277 return true; 278 } 279 280 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const { 281 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), 282 /*Is64Bit=*/false); 283 } 284 285 void RISCV32TargetInfo::fillValidCPUList( 286 SmallVectorImpl<StringRef> &Values) const { 287 llvm::RISCV::fillValidCPUArchList(Values, false); 288 } 289 290 bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const { 291 return llvm::RISCV::checkTuneCPUKind( 292 llvm::RISCV::parseTuneCPUKind(Name, false), 293 /*Is64Bit=*/false); 294 } 295 296 void RISCV32TargetInfo::fillValidTuneCPUList( 297 SmallVectorImpl<StringRef> &Values) const { 298 llvm::RISCV::fillValidTuneCPUArchList(Values, false); 299 } 300 301 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const { 302 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), 303 /*Is64Bit=*/true); 304 } 305 306 void RISCV64TargetInfo::fillValidCPUList( 307 SmallVectorImpl<StringRef> &Values) const { 308 llvm::RISCV::fillValidCPUArchList(Values, true); 309 } 310 311 bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const { 312 return llvm::RISCV::checkTuneCPUKind( 313 llvm::RISCV::parseTuneCPUKind(Name, true), 314 /*Is64Bit=*/true); 315 } 316 317 void RISCV64TargetInfo::fillValidTuneCPUList( 318 SmallVectorImpl<StringRef> &Values) const { 319 llvm::RISCV::fillValidTuneCPUArchList(Values, true); 320 } 321