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 17 using namespace clang; 18 using namespace clang::targets; 19 20 ArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const { 21 static const char *const GCCRegNames[] = { 22 // Integer registers 23 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", 24 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", 25 "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", 26 "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", 27 28 // Floating point registers 29 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", 30 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", 31 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", 32 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"}; 33 return llvm::makeArrayRef(GCCRegNames); 34 } 35 36 ArrayRef<TargetInfo::GCCRegAlias> RISCVTargetInfo::getGCCRegAliases() const { 37 static const TargetInfo::GCCRegAlias GCCRegAliases[] = { 38 {{"zero"}, "x0"}, {{"ra"}, "x1"}, {{"sp"}, "x2"}, {{"gp"}, "x3"}, 39 {{"tp"}, "x4"}, {{"t0"}, "x5"}, {{"t1"}, "x6"}, {{"t2"}, "x7"}, 40 {{"s0"}, "x8"}, {{"s1"}, "x9"}, {{"a0"}, "x10"}, {{"a1"}, "x11"}, 41 {{"a2"}, "x12"}, {{"a3"}, "x13"}, {{"a4"}, "x14"}, {{"a5"}, "x15"}, 42 {{"a6"}, "x16"}, {{"a7"}, "x17"}, {{"s2"}, "x18"}, {{"s3"}, "x19"}, 43 {{"s4"}, "x20"}, {{"s5"}, "x21"}, {{"s6"}, "x22"}, {{"s7"}, "x23"}, 44 {{"s8"}, "x24"}, {{"s9"}, "x25"}, {{"s10"}, "x26"}, {{"s11"}, "x27"}, 45 {{"t3"}, "x28"}, {{"t4"}, "x29"}, {{"t5"}, "x30"}, {{"t6"}, "x31"}, 46 {{"ft0"}, "f0"}, {{"ft1"}, "f1"}, {{"ft2"}, "f2"}, {{"ft3"}, "f3"}, 47 {{"ft4"}, "f4"}, {{"ft5"}, "f5"}, {{"ft6"}, "f6"}, {{"ft7"}, "f7"}, 48 {{"fs0"}, "f8"}, {{"fs1"}, "f9"}, {{"fa0"}, "f10"}, {{"fa1"}, "f11"}, 49 {{"fa2"}, "f12"}, {{"fa3"}, "f13"}, {{"fa4"}, "f14"}, {{"fa5"}, "f15"}, 50 {{"fa6"}, "f16"}, {{"fa7"}, "f17"}, {{"fs2"}, "f18"}, {{"fs3"}, "f19"}, 51 {{"fs4"}, "f20"}, {{"fs5"}, "f21"}, {{"fs6"}, "f22"}, {{"fs7"}, "f23"}, 52 {{"fs8"}, "f24"}, {{"fs9"}, "f25"}, {{"fs10"}, "f26"}, {{"fs11"}, "f27"}, 53 {{"ft8"}, "f28"}, {{"ft9"}, "f29"}, {{"ft10"}, "f30"}, {{"ft11"}, "f31"}}; 54 return llvm::makeArrayRef(GCCRegAliases); 55 } 56 57 bool RISCVTargetInfo::validateAsmConstraint( 58 const char *&Name, TargetInfo::ConstraintInfo &Info) const { 59 switch (*Name) { 60 default: 61 return false; 62 case 'I': 63 // A 12-bit signed immediate. 64 Info.setRequiresImmediate(-2048, 2047); 65 return true; 66 case 'J': 67 // Integer zero. 68 Info.setRequiresImmediate(0); 69 return true; 70 case 'K': 71 // A 5-bit unsigned immediate for CSR access instructions. 72 Info.setRequiresImmediate(0, 31); 73 return true; 74 case 'f': 75 // A floating-point register. 76 Info.setAllowsRegister(); 77 return true; 78 } 79 } 80 81 void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, 82 MacroBuilder &Builder) const { 83 Builder.defineMacro("__ELF__"); 84 Builder.defineMacro("__riscv"); 85 bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; 86 Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32"); 87 // TODO: modify when more code models are supported. 88 Builder.defineMacro("__riscv_cmodel_medlow"); 89 90 StringRef ABIName = getABI(); 91 if (ABIName == "ilp32f" || ABIName == "lp64f") 92 Builder.defineMacro("__riscv_float_abi_single"); 93 else if (ABIName == "ilp32d" || ABIName == "lp64d") 94 Builder.defineMacro("__riscv_float_abi_double"); 95 else if (ABIName == "ilp32e") 96 Builder.defineMacro("__riscv_abi_rve"); 97 else 98 Builder.defineMacro("__riscv_float_abi_soft"); 99 100 if (HasM) { 101 Builder.defineMacro("__riscv_mul"); 102 Builder.defineMacro("__riscv_div"); 103 Builder.defineMacro("__riscv_muldiv"); 104 } 105 106 if (HasA) 107 Builder.defineMacro("__riscv_atomic"); 108 109 if (HasF || HasD) { 110 Builder.defineMacro("__riscv_flen", HasD ? "64" : "32"); 111 Builder.defineMacro("__riscv_fdiv"); 112 Builder.defineMacro("__riscv_fsqrt"); 113 } 114 115 if (HasC) 116 Builder.defineMacro("__riscv_compressed"); 117 } 118 119 /// Return true if has this feature, need to sync with handleTargetFeatures. 120 bool RISCVTargetInfo::hasFeature(StringRef Feature) const { 121 bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; 122 return llvm::StringSwitch<bool>(Feature) 123 .Case("riscv", true) 124 .Case("riscv32", !Is64Bit) 125 .Case("riscv64", Is64Bit) 126 .Case("m", HasM) 127 .Case("a", HasA) 128 .Case("f", HasF) 129 .Case("d", HasD) 130 .Case("c", HasC) 131 .Default(false); 132 } 133 134 /// Perform initialization based on the user configured set of features. 135 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 136 DiagnosticsEngine &Diags) { 137 for (const auto &Feature : Features) { 138 if (Feature == "+m") 139 HasM = true; 140 else if (Feature == "+a") 141 HasA = true; 142 else if (Feature == "+f") 143 HasF = true; 144 else if (Feature == "+d") 145 HasD = true; 146 else if (Feature == "+c") 147 HasC = true; 148 } 149 150 return true; 151 } 152