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