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   }
69 
70   if (hasFeature("hvx-length64b")) {
71     Builder.defineMacro("__HVX__");
72     Builder.defineMacro("__HVX_ARCH__", HVXVersion);
73     Builder.defineMacro("__HVX_LENGTH__", "64");
74   }
75 
76   if (hasFeature("hvx-length128b")) {
77     Builder.defineMacro("__HVX__");
78     Builder.defineMacro("__HVX_ARCH__", HVXVersion);
79     Builder.defineMacro("__HVX_LENGTH__", "128");
80     if (DefineHvxDbl)
81       Builder.defineMacro("__HVXDBL__");
82   }
83 
84   if (hasFeature("audio")) {
85     Builder.defineMacro("__HEXAGON_AUDIO__");
86   }
87 
88   std::string NumPhySlots = isTinyCore() ? "3" : "4";
89   Builder.defineMacro("__HEXAGON_PHYSICAL_SLOTS__", NumPhySlots);
90 }
91 
92 bool HexagonTargetInfo::initFeatureMap(
93     llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
94     const std::vector<std::string> &FeaturesVec) const {
95   if (isTinyCore())
96     Features["audio"] = true;
97 
98   StringRef CPUFeature = CPU;
99   CPUFeature.consume_front("hexagon");
100   CPUFeature.consume_back("t");
101   if (!CPUFeature.empty())
102     Features[CPUFeature] = true;
103 
104   Features["long-calls"] = false;
105 
106   return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
107 }
108 
109 bool HexagonTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
110                                              DiagnosticsEngine &Diags) {
111   for (auto &F : Features) {
112     if (F == "+hvx-length64b")
113       HasHVX = HasHVX64B = true;
114     else if (F == "+hvx-length128b")
115       HasHVX = HasHVX128B = true;
116     else if (F.find("+hvxv") != std::string::npos) {
117       HasHVX = true;
118       HVXVersion = F.substr(std::string("+hvxv").length());
119     } else if (F == "-hvx")
120       HasHVX = HasHVX64B = HasHVX128B = false;
121     else if (F == "+long-calls")
122       UseLongCalls = true;
123     else if (F == "-long-calls")
124       UseLongCalls = false;
125     else if (F == "+audio")
126       HasAudio = true;
127   }
128   return true;
129 }
130 
131 const char *const HexagonTargetInfo::GCCRegNames[] = {
132     "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",  "r8",
133     "r9",  "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17",
134     "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26",
135     "r27", "r28", "r29", "r30", "r31", "p0",  "p1",  "p2",  "p3",
136     "sa0", "lc0", "sa1", "lc1", "m0",  "m1",  "usr", "ugp",
137     "r1:0", "r3:2", "r5:4", "r7:6", "r9:8", "r11:10", "r13:12", "r15:14",
138     "r17:16", "r19:18", "r21:20", "r23:22", "r25:24", "r27:26", "r29:28",
139     "r31:30"
140 };
141 
142 ArrayRef<const char *> HexagonTargetInfo::getGCCRegNames() const {
143   return llvm::makeArrayRef(GCCRegNames);
144 }
145 
146 const TargetInfo::GCCRegAlias HexagonTargetInfo::GCCRegAliases[] = {
147     {{"sp"}, "r29"},
148     {{"fp"}, "r30"},
149     {{"lr"}, "r31"},
150 };
151 
152 ArrayRef<TargetInfo::GCCRegAlias> HexagonTargetInfo::getGCCRegAliases() const {
153   return llvm::makeArrayRef(GCCRegAliases);
154 }
155 
156 const Builtin::Info HexagonTargetInfo::BuiltinInfo[] = {
157 #define BUILTIN(ID, TYPE, ATTRS)                                               \
158   {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
159 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER)                                    \
160   {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
161 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
162   {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
163 #include "clang/Basic/BuiltinsHexagon.def"
164 };
165 
166 bool HexagonTargetInfo::hasFeature(StringRef Feature) const {
167   std::string VS = "hvxv" + HVXVersion;
168   if (Feature == VS)
169     return true;
170 
171   return llvm::StringSwitch<bool>(Feature)
172       .Case("hexagon", true)
173       .Case("hvx", HasHVX)
174       .Case("hvx-length64b", HasHVX64B)
175       .Case("hvx-length128b", HasHVX128B)
176       .Case("long-calls", UseLongCalls)
177       .Case("audio", HasAudio)
178       .Default(false);
179 }
180 
181 struct CPUSuffix {
182   llvm::StringLiteral Name;
183   llvm::StringLiteral Suffix;
184 };
185 
186 static constexpr CPUSuffix Suffixes[] = {
187     {{"hexagonv5"},  {"5"}},  {{"hexagonv55"},  {"55"}},
188     {{"hexagonv60"}, {"60"}}, {{"hexagonv62"},  {"62"}},
189     {{"hexagonv65"}, {"65"}}, {{"hexagonv66"},  {"66"}},
190     {{"hexagonv67"}, {"67"}}, {{"hexagonv67t"}, {"67t"}},
191 };
192 
193 const char *HexagonTargetInfo::getHexagonCPUSuffix(StringRef Name) {
194   const CPUSuffix *Item = llvm::find_if(
195       Suffixes, [Name](const CPUSuffix &S) { return S.Name == Name; });
196   if (Item == std::end(Suffixes))
197     return nullptr;
198   return Item->Suffix.data();
199 }
200 
201 void HexagonTargetInfo::fillValidCPUList(
202     SmallVectorImpl<StringRef> &Values) const {
203   for (const CPUSuffix &Suffix : Suffixes)
204     Values.push_back(Suffix.Name);
205 }
206 
207 ArrayRef<Builtin::Info> HexagonTargetInfo::getTargetBuiltins() const {
208   return llvm::makeArrayRef(BuiltinInfo, clang::Hexagon::LastTSBuiltin -
209                                              Builtin::FirstTSBuiltin);
210 }
211