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