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