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