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 if (HasM) { 113 Builder.defineMacro("__riscv_mul"); 114 Builder.defineMacro("__riscv_div"); 115 Builder.defineMacro("__riscv_muldiv"); 116 } 117 118 if (HasA) { 119 Builder.defineMacro("__riscv_atomic"); 120 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); 121 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); 122 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); 123 if (Is64Bit) 124 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); 125 } 126 127 if (HasF || HasD) { 128 Builder.defineMacro("__riscv_flen", HasD ? "64" : "32"); 129 Builder.defineMacro("__riscv_fdiv"); 130 Builder.defineMacro("__riscv_fsqrt"); 131 } 132 133 if (HasC) 134 Builder.defineMacro("__riscv_compressed"); 135 136 if (HasB) 137 Builder.defineMacro("__riscv_bitmanip"); 138 139 if (HasZfh) 140 Builder.defineMacro("__riscv_zfh"); 141 } 142 143 /// Return true if has this feature, need to sync with handleTargetFeatures. 144 bool RISCVTargetInfo::hasFeature(StringRef Feature) const { 145 bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; 146 return llvm::StringSwitch<bool>(Feature) 147 .Case("riscv", true) 148 .Case("riscv32", !Is64Bit) 149 .Case("riscv64", Is64Bit) 150 .Case("m", HasM) 151 .Case("a", HasA) 152 .Case("f", HasF) 153 .Case("d", HasD) 154 .Case("c", HasC) 155 .Case("experimental-b", HasB) 156 .Case("experimental-zfh", HasZfh) 157 .Default(false); 158 } 159 160 /// Perform initialization based on the user configured set of features. 161 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 162 DiagnosticsEngine &Diags) { 163 for (const auto &Feature : Features) { 164 if (Feature == "+m") 165 HasM = true; 166 else if (Feature == "+a") 167 HasA = true; 168 else if (Feature == "+f") 169 HasF = true; 170 else if (Feature == "+d") 171 HasD = true; 172 else if (Feature == "+c") 173 HasC = true; 174 else if (Feature == "+experimental-b") 175 HasB = true; 176 else if (Feature == "+experimental-zfh") 177 HasZfh = true; 178 } 179 180 return true; 181 } 182 183 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const { 184 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), 185 /*Is64Bit=*/false); 186 } 187 188 void RISCV32TargetInfo::fillValidCPUList( 189 SmallVectorImpl<StringRef> &Values) const { 190 llvm::RISCV::fillValidCPUArchList(Values, false); 191 } 192 193 bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const { 194 return llvm::RISCV::checkTuneCPUKind( 195 llvm::RISCV::parseTuneCPUKind(Name, false), 196 /*Is64Bit=*/false); 197 } 198 199 void RISCV32TargetInfo::fillValidTuneCPUList( 200 SmallVectorImpl<StringRef> &Values) const { 201 llvm::RISCV::fillValidTuneCPUArchList(Values, false); 202 } 203 204 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const { 205 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), 206 /*Is64Bit=*/true); 207 } 208 209 void RISCV64TargetInfo::fillValidCPUList( 210 SmallVectorImpl<StringRef> &Values) const { 211 llvm::RISCV::fillValidCPUArchList(Values, true); 212 } 213 214 bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const { 215 return llvm::RISCV::checkTuneCPUKind( 216 llvm::RISCV::parseTuneCPUKind(Name, true), 217 /*Is64Bit=*/true); 218 } 219 220 void RISCV64TargetInfo::fillValidTuneCPUList( 221 SmallVectorImpl<StringRef> &Values) const { 222 llvm::RISCV::fillValidTuneCPUArchList(Values, true); 223 } 224