1 //===--- RISCV.cpp - Implement RISCV target feature support ---------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements RISCV TargetInfo objects.
11 //===----------------------------------------------------------------------===//
14 #include "clang/Basic/MacroBuilder.h"
15 #include "llvm/ADT/StringSwitch.h"
16 #include "llvm/Support/TargetParser.h"
18 using namespace clang;
19 using namespace clang::targets;
21 ArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const {
22 static const char *const GCCRegNames[] = {
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",
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);
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);
58 bool RISCVTargetInfo::validateAsmConstraint(
59 const char *&Name, TargetInfo::ConstraintInfo &Info) const {
64 // A 12-bit signed immediate.
65 Info.setRequiresImmediate(-2048, 2047);
69 Info.setRequiresImmediate(0);
72 // A 5-bit unsigned immediate for CSR access instructions.
73 Info.setRequiresImmediate(0, 31);
76 // A floating-point register.
77 Info.setAllowsRegister();
80 // An address that is held in a general-purpose register.
81 Info.setAllowsMemory();
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")
96 if (CodeModel == "small")
97 Builder.defineMacro("__riscv_cmodel_medlow");
98 else if (CodeModel == "medium")
99 Builder.defineMacro("__riscv_cmodel_medany");
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");
107 Builder.defineMacro("__riscv_float_abi_soft");
109 if (ABIName == "ilp32e")
110 Builder.defineMacro("__riscv_abi_rve");
113 Builder.defineMacro("__riscv_mul");
114 Builder.defineMacro("__riscv_div");
115 Builder.defineMacro("__riscv_muldiv");
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");
124 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
128 Builder.defineMacro("__riscv_flen", HasD ? "64" : "32");
129 Builder.defineMacro("__riscv_fdiv");
130 Builder.defineMacro("__riscv_fsqrt");
134 Builder.defineMacro("__riscv_compressed");
137 Builder.defineMacro("__riscv_bitmanip");
140 /// Return true if has this feature, need to sync with handleTargetFeatures.
141 bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
142 bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64;
143 return llvm::StringSwitch<bool>(Feature)
145 .Case("riscv32", !Is64Bit)
146 .Case("riscv64", Is64Bit)
152 .Case("experimental-b", HasB)
156 /// Perform initialization based on the user configured set of features.
157 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
158 DiagnosticsEngine &Diags) {
159 for (const auto &Feature : Features) {
162 else if (Feature == "+a")
164 else if (Feature == "+f")
166 else if (Feature == "+d")
168 else if (Feature == "+c")
170 else if (Feature == "+experimental-b")
177 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const {
178 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
182 void RISCV32TargetInfo::fillValidCPUList(
183 SmallVectorImpl<StringRef> &Values) const {
184 llvm::RISCV::fillValidCPUArchList(Values, false);
187 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
188 return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
192 void RISCV64TargetInfo::fillValidCPUList(
193 SmallVectorImpl<StringRef> &Values) const {
194 llvm::RISCV::fillValidCPUArchList(Values, true);