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