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 if (CodeModel == "default") 130 CodeModel = "small"; 131 132 if (CodeModel == "small") 133 Builder.defineMacro("__riscv_cmodel_medlow"); 134 else if (CodeModel == "medium") 135 Builder.defineMacro("__riscv_cmodel_medany"); 136 137 StringRef ABIName = getABI(); 138 if (ABIName == "ilp32f" || ABIName == "lp64f") 139 Builder.defineMacro("__riscv_float_abi_single"); 140 else if (ABIName == "ilp32d" || ABIName == "lp64d") 141 Builder.defineMacro("__riscv_float_abi_double"); 142 else 143 Builder.defineMacro("__riscv_float_abi_soft"); 144 145 if (ABIName == "ilp32e") 146 Builder.defineMacro("__riscv_abi_rve"); 147 148 Builder.defineMacro("__riscv_arch_test"); 149 150 for (auto &Extension : ISAInfo->getExtensions()) { 151 auto ExtName = Extension.first; 152 auto ExtInfo = Extension.second; 153 unsigned Version = 154 (ExtInfo.MajorVersion * 1000000) + (ExtInfo.MinorVersion * 1000); 155 156 Builder.defineMacro(Twine("__riscv_", ExtName), Twine(Version)); 157 } 158 159 if (ISAInfo->hasExtension("m")) { 160 Builder.defineMacro("__riscv_mul"); 161 Builder.defineMacro("__riscv_div"); 162 Builder.defineMacro("__riscv_muldiv"); 163 } 164 165 if (ISAInfo->hasExtension("a")) { 166 Builder.defineMacro("__riscv_atomic"); 167 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); 168 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); 169 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); 170 if (Is64Bit) 171 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); 172 } 173 174 if (FLen) { 175 Builder.defineMacro("__riscv_flen", Twine(FLen)); 176 Builder.defineMacro("__riscv_fdiv"); 177 Builder.defineMacro("__riscv_fsqrt"); 178 } 179 180 if (MinVLen) 181 Builder.defineMacro("__riscv_v_min_vlen", Twine(MinVLen)); 182 183 if (ISAInfo->hasExtension("c")) 184 Builder.defineMacro("__riscv_compressed"); 185 186 if (ISAInfo->hasExtension("v")) 187 Builder.defineMacro("__riscv_vector"); 188 } 189 190 const Builtin::Info RISCVTargetInfo::BuiltinInfo[] = { 191 #define BUILTIN(ID, TYPE, ATTRS) \ 192 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, 193 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ 194 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE}, 195 #include "clang/Basic/BuiltinsRISCVVector.def" 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/BuiltinsRISCV.def" 201 }; 202 203 ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const { 204 return llvm::makeArrayRef(BuiltinInfo, clang::RISCV::LastTSBuiltin - 205 Builtin::FirstTSBuiltin); 206 } 207 208 bool RISCVTargetInfo::initFeatureMap( 209 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, 210 const std::vector<std::string> &FeaturesVec) const { 211 212 if (getTriple().getArch() == llvm::Triple::riscv64) 213 Features["64bit"] = true; 214 215 return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); 216 } 217 218 /// Return true if has this feature, need to sync with handleTargetFeatures. 219 bool RISCVTargetInfo::hasFeature(StringRef Feature) const { 220 bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; 221 auto Result = llvm::StringSwitch<Optional<bool>>(Feature) 222 .Case("riscv", true) 223 .Case("riscv32", !Is64Bit) 224 .Case("riscv64", Is64Bit) 225 .Case("64bit", Is64Bit) 226 .Default(None); 227 if (Result.hasValue()) 228 return Result.getValue(); 229 230 if (ISAInfo->isSupportedExtensionFeature(Feature)) 231 return ISAInfo->hasExtension(Feature); 232 233 return false; 234 } 235 236 /// Perform initialization based on the user configured set of features. 237 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 238 DiagnosticsEngine &Diags) { 239 unsigned XLen = getTriple().isArch64Bit() ? 64 : 32; 240 auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, Features); 241 if (!ParseResult) { 242 std::string Buffer; 243 llvm::raw_string_ostream OutputErrMsg(Buffer); 244 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) { 245 OutputErrMsg << ErrMsg.getMessage(); 246 }); 247 Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str(); 248 return false; 249 } else { 250 ISAInfo = std::move(*ParseResult); 251 } 252 253 if (ABI.empty()) 254 ABI = llvm::RISCV::computeDefaultABIFromArch(*ISAInfo).str(); 255 256 return true; 257 } 258 259 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const { 260 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), 261 /*Is64Bit=*/false); 262 } 263 264 void RISCV32TargetInfo::fillValidCPUList( 265 SmallVectorImpl<StringRef> &Values) const { 266 llvm::RISCV::fillValidCPUArchList(Values, false); 267 } 268 269 bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const { 270 return llvm::RISCV::checkTuneCPUKind( 271 llvm::RISCV::parseTuneCPUKind(Name, false), 272 /*Is64Bit=*/false); 273 } 274 275 void RISCV32TargetInfo::fillValidTuneCPUList( 276 SmallVectorImpl<StringRef> &Values) const { 277 llvm::RISCV::fillValidTuneCPUArchList(Values, false); 278 } 279 280 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const { 281 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), 282 /*Is64Bit=*/true); 283 } 284 285 void RISCV64TargetInfo::fillValidCPUList( 286 SmallVectorImpl<StringRef> &Values) const { 287 llvm::RISCV::fillValidCPUArchList(Values, true); 288 } 289 290 bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const { 291 return llvm::RISCV::checkTuneCPUKind( 292 llvm::RISCV::parseTuneCPUKind(Name, true), 293 /*Is64Bit=*/true); 294 } 295 296 void RISCV64TargetInfo::fillValidTuneCPUList( 297 SmallVectorImpl<StringRef> &Values) const { 298 llvm::RISCV::fillValidTuneCPUArchList(Values, true); 299 } 300