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 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8",
136 "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17",
137 "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26",
138 "r27", "r28", "r29", "r30", "r31", "p0", "p1", "p2", "p3",
139 "sa0", "lc0", "sa1", "lc1", "m0", "m1", "usr", "ugp", "cs0", "cs1",
140 "r1:0", "r3:2", "r5:4", "r7:6", "r9:8", "r11:10", "r13:12", "r15:14",
141 "r17:16", "r19:18", "r21:20", "r23:22", "r25:24", "r27:26", "r29:28",
142 "r31:30"
143 };
144
getGCCRegNames() const145 ArrayRef<const char *> HexagonTargetInfo::getGCCRegNames() const {
146 return llvm::makeArrayRef(GCCRegNames);
147 }
148
149 const TargetInfo::GCCRegAlias HexagonTargetInfo::GCCRegAliases[] = {
150 {{"sp"}, "r29"},
151 {{"fp"}, "r30"},
152 {{"lr"}, "r31"},
153 };
154
getGCCRegAliases() const155 ArrayRef<TargetInfo::GCCRegAlias> HexagonTargetInfo::getGCCRegAliases() const {
156 return llvm::makeArrayRef(GCCRegAliases);
157 }
158
159 const Builtin::Info HexagonTargetInfo::BuiltinInfo[] = {
160 #define BUILTIN(ID, TYPE, ATTRS) \
161 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
162 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
163 {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
164 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
165 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE},
166 #include "clang/Basic/BuiltinsHexagon.def"
167 };
168
hasFeature(StringRef Feature) const169 bool HexagonTargetInfo::hasFeature(StringRef Feature) const {
170 std::string VS = "hvxv" + HVXVersion;
171 if (Feature == VS)
172 return true;
173
174 return llvm::StringSwitch<bool>(Feature)
175 .Case("hexagon", true)
176 .Case("hvx", HasHVX)
177 .Case("hvx-length64b", HasHVX64B)
178 .Case("hvx-length128b", HasHVX128B)
179 .Case("long-calls", UseLongCalls)
180 .Case("audio", HasAudio)
181 .Default(false);
182 }
183
184 struct CPUSuffix {
185 llvm::StringLiteral Name;
186 llvm::StringLiteral Suffix;
187 };
188
189 static constexpr CPUSuffix Suffixes[] = {
190 {{"hexagonv5"}, {"5"}}, {{"hexagonv55"}, {"55"}},
191 {{"hexagonv60"}, {"60"}}, {{"hexagonv62"}, {"62"}},
192 {{"hexagonv65"}, {"65"}}, {{"hexagonv66"}, {"66"}},
193 {{"hexagonv67"}, {"67"}}, {{"hexagonv67t"}, {"67t"}},
194 {{"hexagonv68"}, {"68"}},
195 };
196
getHexagonCPUSuffix(StringRef Name)197 const char *HexagonTargetInfo::getHexagonCPUSuffix(StringRef Name) {
198 const CPUSuffix *Item = llvm::find_if(
199 Suffixes, [Name](const CPUSuffix &S) { return S.Name == Name; });
200 if (Item == std::end(Suffixes))
201 return nullptr;
202 return Item->Suffix.data();
203 }
204
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const205 void HexagonTargetInfo::fillValidCPUList(
206 SmallVectorImpl<StringRef> &Values) const {
207 for (const CPUSuffix &Suffix : Suffixes)
208 Values.push_back(Suffix.Name);
209 }
210
getTargetBuiltins() const211 ArrayRef<Builtin::Info> HexagonTargetInfo::getTargetBuiltins() const {
212 return llvm::makeArrayRef(BuiltinInfo, clang::Hexagon::LastTSBuiltin -
213 Builtin::FirstTSBuiltin);
214 }
215