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   }
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 
95 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 
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 
168 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 
178 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 
192 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 
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 
228 void HexagonTargetInfo::fillValidCPUList(
229     SmallVectorImpl<StringRef> &Values) const {
230   for (const CPUSuffix &Suffix : Suffixes)
231     Values.push_back(Suffix.Name);
232 }
233 
234 ArrayRef<Builtin::Info> HexagonTargetInfo::getTargetBuiltins() const {
235   return llvm::makeArrayRef(BuiltinInfo, clang::Hexagon::LastTSBuiltin -
236                                              Builtin::FirstTSBuiltin);
237 }
238