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 case 'A': 79 // An address that is held in a general-purpose register. 80 Info.setAllowsMemory(); 81 return true; 82 } 83 } 84 85 void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, 86 MacroBuilder &Builder) const { 87 Builder.defineMacro("__ELF__"); 88 Builder.defineMacro("__riscv"); 89 bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; 90 Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32"); 91 // TODO: modify when more code models are supported. 92 Builder.defineMacro("__riscv_cmodel_medlow"); 93 94 StringRef ABIName = getABI(); 95 if (ABIName == "ilp32f" || ABIName == "lp64f") 96 Builder.defineMacro("__riscv_float_abi_single"); 97 else if (ABIName == "ilp32d" || ABIName == "lp64d") 98 Builder.defineMacro("__riscv_float_abi_double"); 99 else 100 Builder.defineMacro("__riscv_float_abi_soft"); 101 102 if (ABIName == "ilp32e") 103 Builder.defineMacro("__riscv_abi_rve"); 104 105 if (HasM) { 106 Builder.defineMacro("__riscv_mul"); 107 Builder.defineMacro("__riscv_div"); 108 Builder.defineMacro("__riscv_muldiv"); 109 } 110 111 if (HasA) 112 Builder.defineMacro("__riscv_atomic"); 113 114 if (HasF || HasD) { 115 Builder.defineMacro("__riscv_flen", HasD ? "64" : "32"); 116 Builder.defineMacro("__riscv_fdiv"); 117 Builder.defineMacro("__riscv_fsqrt"); 118 } 119 120 if (HasC) 121 Builder.defineMacro("__riscv_compressed"); 122 } 123 124 /// Return true if has this feature, need to sync with handleTargetFeatures. 125 bool RISCVTargetInfo::hasFeature(StringRef Feature) const { 126 bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; 127 return llvm::StringSwitch<bool>(Feature) 128 .Case("riscv", true) 129 .Case("riscv32", !Is64Bit) 130 .Case("riscv64", Is64Bit) 131 .Case("m", HasM) 132 .Case("a", HasA) 133 .Case("f", HasF) 134 .Case("d", HasD) 135 .Case("c", HasC) 136 .Default(false); 137 } 138 139 /// Perform initialization based on the user configured set of features. 140 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 141 DiagnosticsEngine &Diags) { 142 for (const auto &Feature : Features) { 143 if (Feature == "+m") 144 HasM = true; 145 else if (Feature == "+a") 146 HasA = true; 147 else if (Feature == "+f") 148 HasF = true; 149 else if (Feature == "+d") 150 HasD = true; 151 else if (Feature == "+c") 152 HasC = true; 153 } 154 155 return true; 156 } 157