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