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