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