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 if (!CPUFeature.empty())
102 Features[CPUFeature] = true;
103
104 Features["long-calls"] = false;
105
106 return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
107 }
108
handleTargetFeatures(std::vector<std::string> & Features,DiagnosticsEngine & Diags)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
getGCCRegNames() const142 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
getGCCRegAliases() const152 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
hasFeature(StringRef Feature) const166 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
getHexagonCPUSuffix(StringRef Name)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
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const201 void HexagonTargetInfo::fillValidCPUList(
202 SmallVectorImpl<StringRef> &Values) const {
203 for (const CPUSuffix &Suffix : Suffixes)
204 Values.push_back(Suffix.Name);
205 }
206
getTargetBuiltins() const207 ArrayRef<Builtin::Info> HexagonTargetInfo::getTargetBuiltins() const {
208 return llvm::makeArrayRef(BuiltinInfo, clang::Hexagon::LastTSBuiltin -
209 Builtin::FirstTSBuiltin);
210 }
211