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