xref: /freebsd/contrib/llvm-project/clang/lib/Basic/Targets/RISCV.cpp (revision da477bcdc0c335171bb0ed3813f570026de6df85)
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