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