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