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