xref: /freebsd/contrib/llvm-project/clang/lib/Basic/Targets/Hexagon.cpp (revision 5036d9652a5701d00e9e40ea942c278e9f77d33d)
1 //===--- Hexagon.cpp - Implement Hexagon 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 Hexagon TargetInfo objects.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "Hexagon.h"
14 #include "Targets.h"
15 #include "clang/Basic/MacroBuilder.h"
16 #include "clang/Basic/TargetBuiltins.h"
17 #include "llvm/ADT/StringSwitch.h"
18 
19 using namespace clang;
20 using namespace clang::targets;
21 
22 void HexagonTargetInfo::getTargetDefines(const LangOptions &Opts,
23                                          MacroBuilder &Builder) const {
24   Builder.defineMacro("__qdsp6__", "1");
25   Builder.defineMacro("__hexagon__", "1");
26 
27   // The macro __HVXDBL__ is deprecated.
28   bool DefineHvxDbl = false;
29 
30   if (CPU == "hexagonv5") {
31     Builder.defineMacro("__HEXAGON_V5__");
32     Builder.defineMacro("__HEXAGON_ARCH__", "5");
33     if (Opts.HexagonQdsp6Compat) {
34       Builder.defineMacro("__QDSP6_V5__");
35       Builder.defineMacro("__QDSP6_ARCH__", "5");
36     }
37   } else if (CPU == "hexagonv55") {
38     Builder.defineMacro("__HEXAGON_V55__");
39     Builder.defineMacro("__HEXAGON_ARCH__", "55");
40     Builder.defineMacro("__QDSP6_V55__");
41     Builder.defineMacro("__QDSP6_ARCH__", "55");
42   } else if (CPU == "hexagonv60") {
43     DefineHvxDbl = true;
44     Builder.defineMacro("__HEXAGON_V60__");
45     Builder.defineMacro("__HEXAGON_ARCH__", "60");
46     Builder.defineMacro("__QDSP6_V60__");
47     Builder.defineMacro("__QDSP6_ARCH__", "60");
48   } else if (CPU == "hexagonv62") {
49     DefineHvxDbl = true;
50     Builder.defineMacro("__HEXAGON_V62__");
51     Builder.defineMacro("__HEXAGON_ARCH__", "62");
52   } else if (CPU == "hexagonv65") {
53     DefineHvxDbl = true;
54     Builder.defineMacro("__HEXAGON_V65__");
55     Builder.defineMacro("__HEXAGON_ARCH__", "65");
56   } else if (CPU == "hexagonv66") {
57     DefineHvxDbl = true;
58     Builder.defineMacro("__HEXAGON_V66__");
59     Builder.defineMacro("__HEXAGON_ARCH__", "66");
60   } else if (CPU == "hexagonv67") {
61     Builder.defineMacro("__HEXAGON_V67__");
62     Builder.defineMacro("__HEXAGON_ARCH__", "67");
63   } else if (CPU == "hexagonv67t") {
64     Builder.defineMacro("__HEXAGON_V67T__");
65     Builder.defineMacro("__HEXAGON_ARCH__", "67");
66   } else if (CPU == "hexagonv68") {
67     Builder.defineMacro("__HEXAGON_V68__");
68     Builder.defineMacro("__HEXAGON_ARCH__", "68");
69   } else if (CPU == "hexagonv69") {
70     Builder.defineMacro("__HEXAGON_V69__");
71     Builder.defineMacro("__HEXAGON_ARCH__", "69");
72   } else if (CPU == "hexagonv71") {
73     Builder.defineMacro("__HEXAGON_V71__");
74     Builder.defineMacro("__HEXAGON_ARCH__", "71");
75   } else if (CPU == "hexagonv71t") {
76     Builder.defineMacro("__HEXAGON_V71T__");
77     Builder.defineMacro("__HEXAGON_ARCH__", "71");
78   } else if (CPU == "hexagonv73") {
79     Builder.defineMacro("__HEXAGON_V73__");
80     Builder.defineMacro("__HEXAGON_ARCH__", "73");
81   }
82 
83   if (hasFeature("hvx-length64b")) {
84     Builder.defineMacro("__HVX__");
85     Builder.defineMacro("__HVX_ARCH__", HVXVersion);
86     Builder.defineMacro("__HVX_LENGTH__", "64");
87   }
88 
89   if (hasFeature("hvx-length128b")) {
90     Builder.defineMacro("__HVX__");
91     Builder.defineMacro("__HVX_ARCH__", HVXVersion);
92     Builder.defineMacro("__HVX_LENGTH__", "128");
93     if (DefineHvxDbl)
94       Builder.defineMacro("__HVXDBL__");
95   }
96 
97   if (hasFeature("audio")) {
98     Builder.defineMacro("__HEXAGON_AUDIO__");
99   }
100 
101   std::string NumPhySlots = isTinyCore() ? "3" : "4";
102   Builder.defineMacro("__HEXAGON_PHYSICAL_SLOTS__", NumPhySlots);
103 
104   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
105   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
106   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
107   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
108 }
109 
110 bool HexagonTargetInfo::initFeatureMap(
111     llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
112     const std::vector<std::string> &FeaturesVec) const {
113   if (isTinyCore())
114     Features["audio"] = true;
115 
116   StringRef CPUFeature = CPU;
117   CPUFeature.consume_front("hexagon");
118   CPUFeature.consume_back("t");
119   if (!CPUFeature.empty())
120     Features[CPUFeature] = true;
121 
122   Features["long-calls"] = false;
123 
124   return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
125 }
126 
127 bool HexagonTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
128                                              DiagnosticsEngine &Diags) {
129   for (auto &F : Features) {
130     if (F == "+hvx-length64b")
131       HasHVX = HasHVX64B = true;
132     else if (F == "+hvx-length128b")
133       HasHVX = HasHVX128B = true;
134     else if (F.find("+hvxv") != std::string::npos) {
135       HasHVX = true;
136       HVXVersion = F.substr(std::string("+hvxv").length());
137     } else if (F == "-hvx")
138       HasHVX = HasHVX64B = HasHVX128B = false;
139     else if (F == "+long-calls")
140       UseLongCalls = true;
141     else if (F == "-long-calls")
142       UseLongCalls = false;
143     else if (F == "+audio")
144       HasAudio = true;
145   }
146   if (CPU.compare("hexagonv68") >= 0) {
147     HasLegalHalfType = true;
148     HasFloat16 = true;
149   }
150   return true;
151 }
152 
153 const char *const HexagonTargetInfo::GCCRegNames[] = {
154     // Scalar registers:
155     "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
156     "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21",
157     "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
158     "r1:0", "r3:2", "r5:4", "r7:6", "r9:8", "r11:10", "r13:12", "r15:14",
159     "r17:16", "r19:18", "r21:20", "r23:22", "r25:24", "r27:26", "r29:28",
160     "r31:30",
161     // Predicate registers:
162     "p0", "p1", "p2", "p3",
163     // Control registers:
164     "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "c10", "c11",
165     "c12", "c13", "c14", "c15", "c16", "c17", "c18", "c19", "c20", "c21",
166     "c22", "c23", "c24", "c25", "c26", "c27", "c28", "c29", "c30", "c31",
167     "c1:0", "c3:2", "c5:4", "c7:6", "c9:8", "c11:10", "c13:12", "c15:14",
168     "c17:16", "c19:18", "c21:20", "c23:22", "c25:24", "c27:26", "c29:28",
169     "c31:30",
170     // Control register aliases:
171     "sa0", "lc0", "sa1", "lc1", "p3:0", "m0",  "m1",  "usr", "pc", "ugp",
172     "gp", "cs0", "cs1", "upcyclelo", "upcyclehi", "framelimit", "framekey",
173     "pktcountlo", "pktcounthi", "utimerlo", "utimerhi",
174     "upcycle", "pktcount", "utimer",
175     // HVX vector registers:
176     "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
177     "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21",
178     "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
179     "v1:0", "v3:2", "v5:4", "v7:6", "v9:8", "v11:10", "v13:12", "v15:14",
180     "v17:16", "v19:18", "v21:20", "v23:22", "v25:24", "v27:26", "v29:28",
181     "v31:30",
182     "v3:0", "v7:4", "v11:8", "v15:12", "v19:16", "v23:20", "v27:24", "v31:28",
183     // HVX vector predicates:
184     "q0", "q1", "q2", "q3",
185 };
186 
187 ArrayRef<const char *> HexagonTargetInfo::getGCCRegNames() const {
188   return llvm::ArrayRef(GCCRegNames);
189 }
190 
191 const TargetInfo::GCCRegAlias HexagonTargetInfo::GCCRegAliases[] = {
192     {{"sp"}, "r29"},
193     {{"fp"}, "r30"},
194     {{"lr"}, "r31"},
195 };
196 
197 ArrayRef<TargetInfo::GCCRegAlias> HexagonTargetInfo::getGCCRegAliases() const {
198   return llvm::ArrayRef(GCCRegAliases);
199 }
200 
201 static constexpr Builtin::Info BuiltinInfo[] = {
202 #define BUILTIN(ID, TYPE, ATTRS)                                               \
203   {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
204 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER)                                    \
205   {#ID, TYPE, ATTRS, nullptr, HEADER, ALL_LANGUAGES},
206 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
207   {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
208 #include "clang/Basic/BuiltinsHexagon.def"
209 };
210 
211 bool HexagonTargetInfo::hasFeature(StringRef Feature) const {
212   std::string VS = "hvxv" + HVXVersion;
213   if (Feature == VS)
214     return true;
215 
216   return llvm::StringSwitch<bool>(Feature)
217       .Case("hexagon", true)
218       .Case("hvx", HasHVX)
219       .Case("hvx-length64b", HasHVX64B)
220       .Case("hvx-length128b", HasHVX128B)
221       .Case("long-calls", UseLongCalls)
222       .Case("audio", HasAudio)
223       .Default(false);
224 }
225 
226 struct CPUSuffix {
227   llvm::StringLiteral Name;
228   llvm::StringLiteral Suffix;
229 };
230 
231 static constexpr CPUSuffix Suffixes[] = {
232     {{"hexagonv5"},  {"5"}},  {{"hexagonv55"},  {"55"}},
233     {{"hexagonv60"}, {"60"}}, {{"hexagonv62"},  {"62"}},
234     {{"hexagonv65"}, {"65"}}, {{"hexagonv66"},  {"66"}},
235     {{"hexagonv67"}, {"67"}}, {{"hexagonv67t"}, {"67t"}},
236     {{"hexagonv68"}, {"68"}}, {{"hexagonv69"},  {"69"}},
237     {{"hexagonv71"}, {"71"}}, {{"hexagonv71t"},  {"71t"}},
238     {{"hexagonv73"}, {"73"}},
239 };
240 
241 std::optional<unsigned> HexagonTargetInfo::getHexagonCPURev(StringRef Name) {
242   StringRef Arch = Name;
243   Arch.consume_front("hexagonv");
244   Arch.consume_back("t");
245 
246   unsigned Val;
247   if (!Arch.getAsInteger(0, Val))
248     return Val;
249 
250   return std::nullopt;
251 }
252 
253 const char *HexagonTargetInfo::getHexagonCPUSuffix(StringRef Name) {
254   const CPUSuffix *Item = llvm::find_if(
255       Suffixes, [Name](const CPUSuffix &S) { return S.Name == Name; });
256   if (Item == std::end(Suffixes))
257     return nullptr;
258   return Item->Suffix.data();
259 }
260 
261 void HexagonTargetInfo::fillValidCPUList(
262     SmallVectorImpl<StringRef> &Values) const {
263   for (const CPUSuffix &Suffix : Suffixes)
264     Values.push_back(Suffix.Name);
265 }
266 
267 ArrayRef<Builtin::Info> HexagonTargetInfo::getTargetBuiltins() const {
268   return llvm::ArrayRef(BuiltinInfo, clang::Hexagon::LastTSBuiltin -
269                                          Builtin::FirstTSBuiltin);
270 }
271