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 121 if (HasF || HasD) { 122 Builder.defineMacro("__riscv_flen", HasD ? "64" : "32"); 123 Builder.defineMacro("__riscv_fdiv"); 124 Builder.defineMacro("__riscv_fsqrt"); 125 } 126 127 if (HasC) 128 Builder.defineMacro("__riscv_compressed"); 129 130 if (HasB) 131 Builder.defineMacro("__riscv_bitmanip"); 132 } 133 134 /// Return true if has this feature, need to sync with handleTargetFeatures. 135 bool RISCVTargetInfo::hasFeature(StringRef Feature) const { 136 bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; 137 return llvm::StringSwitch<bool>(Feature) 138 .Case("riscv", true) 139 .Case("riscv32", !Is64Bit) 140 .Case("riscv64", Is64Bit) 141 .Case("m", HasM) 142 .Case("a", HasA) 143 .Case("f", HasF) 144 .Case("d", HasD) 145 .Case("c", HasC) 146 .Case("experimental-b", HasB) 147 .Default(false); 148 } 149 150 /// Perform initialization based on the user configured set of features. 151 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 152 DiagnosticsEngine &Diags) { 153 for (const auto &Feature : Features) { 154 if (Feature == "+m") 155 HasM = true; 156 else if (Feature == "+a") 157 HasA = true; 158 else if (Feature == "+f") 159 HasF = true; 160 else if (Feature == "+d") 161 HasD = true; 162 else if (Feature == "+c") 163 HasC = true; 164 else if (Feature == "+experimental-b") 165 HasB = true; 166 } 167 168 return true; 169 } 170 171 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const { 172 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), 173 /*Is64Bit=*/false); 174 } 175 176 void RISCV32TargetInfo::fillValidCPUList( 177 SmallVectorImpl<StringRef> &Values) const { 178 llvm::RISCV::fillValidCPUArchList(Values, false); 179 } 180 181 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const { 182 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name), 183 /*Is64Bit=*/true); 184 } 185 186 void RISCV64TargetInfo::fillValidCPUList( 187 SmallVectorImpl<StringRef> &Values) const { 188 llvm::RISCV::fillValidCPUArchList(Values, true); 189 } 190