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