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 const char *HexagonTargetInfo::getHexagonCPUSuffix(StringRef Name) {
242   const CPUSuffix *Item = llvm::find_if(
243       Suffixes, [Name](const CPUSuffix &S) { return S.Name == Name; });
244   if (Item == std::end(Suffixes))
245     return nullptr;
246   return Item->Suffix.data();
247 }
248 
249 void HexagonTargetInfo::fillValidCPUList(
250     SmallVectorImpl<StringRef> &Values) const {
251   for (const CPUSuffix &Suffix : Suffixes)
252     Values.push_back(Suffix.Name);
253 }
254 
255 ArrayRef<Builtin::Info> HexagonTargetInfo::getTargetBuiltins() const {
256   return llvm::ArrayRef(BuiltinInfo, clang::Hexagon::LastTSBuiltin -
257                                          Builtin::FirstTSBuiltin);
258 }
259