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 == "hexagonv4") {
29     Builder.defineMacro("__HEXAGON_V4__");
30     Builder.defineMacro("__HEXAGON_ARCH__", "4");
31     if (Opts.HexagonQdsp6Compat) {
32       Builder.defineMacro("__QDSP6_V4__");
33       Builder.defineMacro("__QDSP6_ARCH__", "4");
34     }
35   } else if (CPU == "hexagonv5") {
36     Builder.defineMacro("__HEXAGON_V5__");
37     Builder.defineMacro("__HEXAGON_ARCH__", "5");
38     if (Opts.HexagonQdsp6Compat) {
39       Builder.defineMacro("__QDSP6_V5__");
40       Builder.defineMacro("__QDSP6_ARCH__", "5");
41     }
42   } else if (CPU == "hexagonv55") {
43     Builder.defineMacro("__HEXAGON_V55__");
44     Builder.defineMacro("__HEXAGON_ARCH__", "55");
45     Builder.defineMacro("__QDSP6_V55__");
46     Builder.defineMacro("__QDSP6_ARCH__", "55");
47   } else if (CPU == "hexagonv60") {
48     Builder.defineMacro("__HEXAGON_V60__");
49     Builder.defineMacro("__HEXAGON_ARCH__", "60");
50     Builder.defineMacro("__QDSP6_V60__");
51     Builder.defineMacro("__QDSP6_ARCH__", "60");
52   } else if (CPU == "hexagonv62") {
53     Builder.defineMacro("__HEXAGON_V62__");
54     Builder.defineMacro("__HEXAGON_ARCH__", "62");
55   } else if (CPU == "hexagonv65") {
56     Builder.defineMacro("__HEXAGON_V65__");
57     Builder.defineMacro("__HEXAGON_ARCH__", "65");
58   }
59 
60   if (hasFeature("hvx-length64b")) {
61     Builder.defineMacro("__HVX__");
62     Builder.defineMacro("__HVX_ARCH__", HVXVersion);
63     Builder.defineMacro("__HVX_LENGTH__", "64");
64   }
65 
66   if (hasFeature("hvx-length128b")) {
67     Builder.defineMacro("__HVX__");
68     Builder.defineMacro("__HVX_ARCH__", HVXVersion);
69     Builder.defineMacro("__HVX_LENGTH__", "128");
70     // FIXME: This macro is deprecated.
71     Builder.defineMacro("__HVXDBL__");
72   }
73 }
74 
75 bool HexagonTargetInfo::initFeatureMap(
76     llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
77     const std::vector<std::string> &FeaturesVec) const {
78   Features["long-calls"] = false;
79 
80   return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
81 }
82 
83 bool HexagonTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
84                                              DiagnosticsEngine &Diags) {
85   for (auto &F : Features) {
86     if (F == "+hvx-length64b")
87       HasHVX = HasHVX64B = true;
88     else if (F == "+hvx-length128b")
89       HasHVX = HasHVX128B = true;
90     else if (F.find("+hvxv") != std::string::npos) {
91       HasHVX = true;
92       HVXVersion = F.substr(std::string("+hvxv").length());
93     } else if (F == "-hvx")
94       HasHVX = HasHVX64B = HasHVX128B = false;
95     else if (F == "+long-calls")
96       UseLongCalls = true;
97     else if (F == "-long-calls")
98       UseLongCalls = false;
99   }
100   return true;
101 }
102 
103 const char *const HexagonTargetInfo::GCCRegNames[] = {
104     "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",  "r8",
105     "r9",  "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17",
106     "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26",
107     "r27", "r28", "r29", "r30", "r31", "p0",  "p1",  "p2",  "p3",
108     "sa0", "lc0", "sa1", "lc1", "m0",  "m1",  "usr", "ugp"
109 };
110 
111 ArrayRef<const char *> HexagonTargetInfo::getGCCRegNames() const {
112   return llvm::makeArrayRef(GCCRegNames);
113 }
114 
115 const TargetInfo::GCCRegAlias HexagonTargetInfo::GCCRegAliases[] = {
116     {{"sp"}, "r29"},
117     {{"fp"}, "r30"},
118     {{"lr"}, "r31"},
119 };
120 
121 ArrayRef<TargetInfo::GCCRegAlias> HexagonTargetInfo::getGCCRegAliases() const {
122   return llvm::makeArrayRef(GCCRegAliases);
123 }
124 
125 const Builtin::Info HexagonTargetInfo::BuiltinInfo[] = {
126 #define BUILTIN(ID, TYPE, ATTRS)                                               \
127   {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
128 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER)                                    \
129   {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
130 #include "clang/Basic/BuiltinsHexagon.def"
131 };
132 
133 bool HexagonTargetInfo::hasFeature(StringRef Feature) const {
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     {{"hexagonv4"}, {"4"}},   {{"hexagonv5"}, {"5"}},
150     {{"hexagonv55"}, {"55"}}, {{"hexagonv60"}, {"60"}},
151     {{"hexagonv62"}, {"62"}}, {{"hexagonv65"}, {"65"}},
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