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
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const22 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
initFeatureMap(llvm::StringMap<bool> & Features,DiagnosticsEngine & Diags,StringRef CPU,const std::vector<std::string> & FeaturesVec) const112 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
handleTargetFeatures(std::vector<std::string> & Features,DiagnosticsEngine & Diags)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
getGCCRegNames() const189 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
getGCCRegAliases() const199 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
hasFeature(StringRef Feature) const213 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
getHexagonCPUSuffix(StringRef Name)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
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const251 void HexagonTargetInfo::fillValidCPUList(
252 SmallVectorImpl<StringRef> &Values) const {
253 for (const CPUSuffix &Suffix : Suffixes)
254 Values.push_back(Suffix.Name);
255 }
256
getTargetBuiltins() const257 ArrayRef<Builtin::Info> HexagonTargetInfo::getTargetBuiltins() const {
258 return llvm::ArrayRef(BuiltinInfo, clang::Hexagon::LastTSBuiltin -
259 Builtin::FirstTSBuiltin);
260 }
261