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