Merge commit 28de0fb48 from llvm git (by Luís Marques):
[freebsd.git] / contrib / llvm-project / clang / lib / Basic / Targets / RISCV.cpp
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     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");
123     if (Is64Bit)
124       Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
125   }
126
127   if (HasF || HasD) {
128     Builder.defineMacro("__riscv_flen", HasD ? "64" : "32");
129     Builder.defineMacro("__riscv_fdiv");
130     Builder.defineMacro("__riscv_fsqrt");
131   }
132
133   if (HasC)
134     Builder.defineMacro("__riscv_compressed");
135
136   if (HasB)
137     Builder.defineMacro("__riscv_bitmanip");
138 }
139
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)
144       .Case("riscv", true)
145       .Case("riscv32", !Is64Bit)
146       .Case("riscv64", Is64Bit)
147       .Case("m", HasM)
148       .Case("a", HasA)
149       .Case("f", HasF)
150       .Case("d", HasD)
151       .Case("c", HasC)
152       .Case("experimental-b", HasB)
153       .Default(false);
154 }
155
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) {
160     if (Feature == "+m")
161       HasM = true;
162     else if (Feature == "+a")
163       HasA = true;
164     else if (Feature == "+f")
165       HasF = true;
166     else if (Feature == "+d")
167       HasD = true;
168     else if (Feature == "+c")
169       HasC = true;
170     else if (Feature == "+experimental-b")
171       HasB = true;
172   }
173
174   return true;
175 }
176
177 bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const {
178   return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
179                                    /*Is64Bit=*/false);
180 }
181
182 void RISCV32TargetInfo::fillValidCPUList(
183     SmallVectorImpl<StringRef> &Values) const {
184   llvm::RISCV::fillValidCPUArchList(Values, false);
185 }
186
187 bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
188   return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
189                                    /*Is64Bit=*/true);
190 }
191
192 void RISCV64TargetInfo::fillValidCPUList(
193     SmallVectorImpl<StringRef> &Values) const {
194   llvm::RISCV::fillValidCPUArchList(Values, true);
195 }