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 }
72
73 if (hasFeature("hvx-length64b")) {
74 Builder.defineMacro("__HVX__");
75 Builder.defineMacro("__HVX_ARCH__", HVXVersion);
76 Builder.defineMacro("__HVX_LENGTH__", "64");
77 }
78
79 if (hasFeature("hvx-length128b")) {
80 Builder.defineMacro("__HVX__");
81 Builder.defineMacro("__HVX_ARCH__", HVXVersion);
82 Builder.defineMacro("__HVX_LENGTH__", "128");
83 if (DefineHvxDbl)
84 Builder.defineMacro("__HVXDBL__");
85 }
86
87 if (hasFeature("audio")) {
88 Builder.defineMacro("__HEXAGON_AUDIO__");
89 }
90
91 std::string NumPhySlots = isTinyCore() ? "3" : "4";
92 Builder.defineMacro("__HEXAGON_PHYSICAL_SLOTS__", NumPhySlots);
93 }
94
initFeatureMap(llvm::StringMap<bool> & Features,DiagnosticsEngine & Diags,StringRef CPU,const std::vector<std::string> & FeaturesVec) const95 bool HexagonTargetInfo::initFeatureMap(
96 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
97 const std::vector<std::string> &FeaturesVec) const {
98 if (isTinyCore())
99 Features["audio"] = true;
100
101 StringRef CPUFeature = CPU;
102 CPUFeature.consume_front("hexagon");
103 CPUFeature.consume_back("t");
104 if (!CPUFeature.empty())
105 Features[CPUFeature] = true;
106
107 Features["long-calls"] = false;
108
109 return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
110 }
111
handleTargetFeatures(std::vector<std::string> & Features,DiagnosticsEngine & Diags)112 bool HexagonTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
113 DiagnosticsEngine &Diags) {
114 for (auto &F : Features) {
115 if (F == "+hvx-length64b")
116 HasHVX = HasHVX64B = true;
117 else if (F == "+hvx-length128b")
118 HasHVX = HasHVX128B = true;
119 else if (F.find("+hvxv") != std::string::npos) {
120 HasHVX = true;
121 HVXVersion = F.substr(std::string("+hvxv").length());
122 } else if (F == "-hvx")
123 HasHVX = HasHVX64B = HasHVX128B = false;
124 else if (F == "+long-calls")
125 UseLongCalls = true;
126 else if (F == "-long-calls")
127 UseLongCalls = false;
128 else if (F == "+audio")
129 HasAudio = true;
130 }
131 return true;
132 }
133
134 const char *const HexagonTargetInfo::GCCRegNames[] = {
135 // Scalar registers:
136 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
137 "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21",
138 "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
139 "r1:0", "r3:2", "r5:4", "r7:6", "r9:8", "r11:10", "r13:12", "r15:14",
140 "r17:16", "r19:18", "r21:20", "r23:22", "r25:24", "r27:26", "r29:28",
141 "r31:30",
142 // Predicate registers:
143 "p0", "p1", "p2", "p3",
144 // Control registers:
145 "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "c10", "c11",
146 "c12", "c13", "c14", "c15", "c16", "c17", "c18", "c19", "c20", "c21",
147 "c22", "c23", "c24", "c25", "c26", "c27", "c28", "c29", "c30", "c31",
148 "c1:0", "c3:2", "c5:4", "c7:6", "c9:8", "c11:10", "c13:12", "c15:14",
149 "c17:16", "c19:18", "c21:20", "c23:22", "c25:24", "c27:26", "c29:28",
150 "c31:30",
151 // Control register aliases:
152 "sa0", "lc0", "sa1", "lc1", "p3:0", "m0", "m1", "usr", "pc", "ugp",
153 "gp", "cs0", "cs1", "upcyclelo", "upcyclehi", "framelimit", "framekey",
154 "pktcountlo", "pktcounthi", "utimerlo", "utimerhi",
155 "upcycle", "pktcount", "utimer",
156 // HVX vector registers:
157 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
158 "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21",
159 "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
160 "v1:0", "v3:2", "v5:4", "v7:6", "v9:8", "v11:10", "v13:12", "v15:14",
161 "v17:16", "v19:18", "v21:20", "v23:22", "v25:24", "v27:26", "v29:28",
162 "v31:30",
163 "v3:0", "v7:4", "v11:8", "v15:12", "v19:16", "v23:20", "v27:24", "v31:28",
164 // HVX vector predicates:
165 "q0", "q1", "q2", "q3",
166 };
167
getGCCRegNames() const168 ArrayRef<const char *> HexagonTargetInfo::getGCCRegNames() const {
169 return llvm::makeArrayRef(GCCRegNames);
170 }
171
172 const TargetInfo::GCCRegAlias HexagonTargetInfo::GCCRegAliases[] = {
173 {{"sp"}, "r29"},
174 {{"fp"}, "r30"},
175 {{"lr"}, "r31"},
176 };
177
getGCCRegAliases() const178 ArrayRef<TargetInfo::GCCRegAlias> HexagonTargetInfo::getGCCRegAliases() const {
179 return llvm::makeArrayRef(GCCRegAliases);
180 }
181
182 const Builtin::Info HexagonTargetInfo::BuiltinInfo[] = {
183 #define BUILTIN(ID, TYPE, ATTRS) \
184 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
185 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
186 {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
187 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
188 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
189 #include "clang/Basic/BuiltinsHexagon.def"
190 };
191
hasFeature(StringRef Feature) const192 bool HexagonTargetInfo::hasFeature(StringRef Feature) const {
193 std::string VS = "hvxv" + HVXVersion;
194 if (Feature == VS)
195 return true;
196
197 return llvm::StringSwitch<bool>(Feature)
198 .Case("hexagon", true)
199 .Case("hvx", HasHVX)
200 .Case("hvx-length64b", HasHVX64B)
201 .Case("hvx-length128b", HasHVX128B)
202 .Case("long-calls", UseLongCalls)
203 .Case("audio", HasAudio)
204 .Default(false);
205 }
206
207 struct CPUSuffix {
208 llvm::StringLiteral Name;
209 llvm::StringLiteral Suffix;
210 };
211
212 static constexpr CPUSuffix Suffixes[] = {
213 {{"hexagonv5"}, {"5"}}, {{"hexagonv55"}, {"55"}},
214 {{"hexagonv60"}, {"60"}}, {{"hexagonv62"}, {"62"}},
215 {{"hexagonv65"}, {"65"}}, {{"hexagonv66"}, {"66"}},
216 {{"hexagonv67"}, {"67"}}, {{"hexagonv67t"}, {"67t"}},
217 {{"hexagonv68"}, {"68"}},
218 };
219
getHexagonCPUSuffix(StringRef Name)220 const char *HexagonTargetInfo::getHexagonCPUSuffix(StringRef Name) {
221 const CPUSuffix *Item = llvm::find_if(
222 Suffixes, [Name](const CPUSuffix &S) { return S.Name == Name; });
223 if (Item == std::end(Suffixes))
224 return nullptr;
225 return Item->Suffix.data();
226 }
227
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const228 void HexagonTargetInfo::fillValidCPUList(
229 SmallVectorImpl<StringRef> &Values) const {
230 for (const CPUSuffix &Suffix : Suffixes)
231 Values.push_back(Suffix.Name);
232 }
233
getTargetBuiltins() const234 ArrayRef<Builtin::Info> HexagonTargetInfo::getTargetBuiltins() const {
235 return llvm::makeArrayRef(BuiltinInfo, clang::Hexagon::LastTSBuiltin -
236 Builtin::FirstTSBuiltin);
237 }
238