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 } else if (CPU == "hexagonv68") { 67 Builder.defineMacro("__HEXAGON_V68__"); 68 Builder.defineMacro("__HEXAGON_ARCH__", "68"); 69 } else if (CPU == "hexagonv69") { 70 Builder.defineMacro("__HEXAGON_V69__"); 71 Builder.defineMacro("__HEXAGON_ARCH__", "69"); 72 } else if (CPU == "hexagonv71") { 73 Builder.defineMacro("__HEXAGON_V71__"); 74 Builder.defineMacro("__HEXAGON_ARCH__", "71"); 75 } else if (CPU == "hexagonv71t") { 76 Builder.defineMacro("__HEXAGON_V71T__"); 77 Builder.defineMacro("__HEXAGON_ARCH__", "71"); 78 } else if (CPU == "hexagonv73") { 79 Builder.defineMacro("__HEXAGON_V73__"); 80 Builder.defineMacro("__HEXAGON_ARCH__", "73"); 81 } else if (CPU == "hexagonv75") { 82 Builder.defineMacro("__HEXAGON_V75__"); 83 Builder.defineMacro("__HEXAGON_ARCH__", "75"); 84 } else if (CPU == "hexagonv79") { 85 Builder.defineMacro("__HEXAGON_V79__"); 86 Builder.defineMacro("__HEXAGON_ARCH__", "79"); 87 } 88 89 if (hasFeature("hvx-length64b")) { 90 Builder.defineMacro("__HVX__"); 91 Builder.defineMacro("__HVX_ARCH__", HVXVersion); 92 Builder.defineMacro("__HVX_LENGTH__", "64"); 93 } 94 95 if (hasFeature("hvx-length128b")) { 96 Builder.defineMacro("__HVX__"); 97 Builder.defineMacro("__HVX_ARCH__", HVXVersion); 98 Builder.defineMacro("__HVX_LENGTH__", "128"); 99 if (DefineHvxDbl) 100 Builder.defineMacro("__HVXDBL__"); 101 } 102 103 if (hasFeature("audio")) { 104 Builder.defineMacro("__HEXAGON_AUDIO__"); 105 } 106 107 std::string NumPhySlots = isTinyCore() ? "3" : "4"; 108 Builder.defineMacro("__HEXAGON_PHYSICAL_SLOTS__", NumPhySlots); 109 110 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); 111 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); 112 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); 113 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); 114 } 115 116 bool HexagonTargetInfo::initFeatureMap( 117 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, 118 const std::vector<std::string> &FeaturesVec) const { 119 if (isTinyCore()) 120 Features["audio"] = true; 121 122 StringRef CPUFeature = CPU; 123 CPUFeature.consume_front("hexagon"); 124 CPUFeature.consume_back("t"); 125 if (!CPUFeature.empty()) 126 Features[CPUFeature] = true; 127 128 Features["long-calls"] = false; 129 130 return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); 131 } 132 133 bool HexagonTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 134 DiagnosticsEngine &Diags) { 135 for (auto &F : Features) { 136 if (F == "+hvx-length64b") 137 HasHVX = HasHVX64B = true; 138 else if (F == "+hvx-length128b") 139 HasHVX = HasHVX128B = true; 140 else if (F.find("+hvxv") != std::string::npos) { 141 HasHVX = true; 142 HVXVersion = F.substr(std::string("+hvxv").length()); 143 } else if (F == "-hvx") 144 HasHVX = HasHVX64B = HasHVX128B = false; 145 else if (F == "+long-calls") 146 UseLongCalls = true; 147 else if (F == "-long-calls") 148 UseLongCalls = false; 149 else if (F == "+audio") 150 HasAudio = true; 151 } 152 if (CPU.compare("hexagonv68") >= 0) { 153 HasLegalHalfType = true; 154 HasFloat16 = true; 155 } 156 return true; 157 } 158 159 const char *const HexagonTargetInfo::GCCRegNames[] = { 160 // Scalar registers: 161 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", 162 "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21", 163 "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", 164 "r1:0", "r3:2", "r5:4", "r7:6", "r9:8", "r11:10", "r13:12", "r15:14", 165 "r17:16", "r19:18", "r21:20", "r23:22", "r25:24", "r27:26", "r29:28", 166 "r31:30", 167 // Predicate registers: 168 "p0", "p1", "p2", "p3", 169 // Control registers: 170 "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "c10", "c11", 171 "c12", "c13", "c14", "c15", "c16", "c17", "c18", "c19", "c20", "c21", 172 "c22", "c23", "c24", "c25", "c26", "c27", "c28", "c29", "c30", "c31", 173 "c1:0", "c3:2", "c5:4", "c7:6", "c9:8", "c11:10", "c13:12", "c15:14", 174 "c17:16", "c19:18", "c21:20", "c23:22", "c25:24", "c27:26", "c29:28", 175 "c31:30", 176 // Control register aliases: 177 "sa0", "lc0", "sa1", "lc1", "p3:0", "m0", "m1", "usr", "pc", "ugp", 178 "gp", "cs0", "cs1", "upcyclelo", "upcyclehi", "framelimit", "framekey", 179 "pktcountlo", "pktcounthi", "utimerlo", "utimerhi", 180 "upcycle", "pktcount", "utimer", 181 // HVX vector registers: 182 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11", 183 "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", 184 "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", 185 "v1:0", "v3:2", "v5:4", "v7:6", "v9:8", "v11:10", "v13:12", "v15:14", 186 "v17:16", "v19:18", "v21:20", "v23:22", "v25:24", "v27:26", "v29:28", 187 "v31:30", 188 "v3:0", "v7:4", "v11:8", "v15:12", "v19:16", "v23:20", "v27:24", "v31:28", 189 // HVX vector predicates: 190 "q0", "q1", "q2", "q3", 191 }; 192 193 ArrayRef<const char *> HexagonTargetInfo::getGCCRegNames() const { 194 return llvm::ArrayRef(GCCRegNames); 195 } 196 197 const TargetInfo::GCCRegAlias HexagonTargetInfo::GCCRegAliases[] = { 198 {{"sp"}, "r29"}, 199 {{"fp"}, "r30"}, 200 {{"lr"}, "r31"}, 201 }; 202 203 ArrayRef<TargetInfo::GCCRegAlias> HexagonTargetInfo::getGCCRegAliases() const { 204 return llvm::ArrayRef(GCCRegAliases); 205 } 206 207 static constexpr Builtin::Info BuiltinInfo[] = { 208 #define BUILTIN(ID, TYPE, ATTRS) \ 209 {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, 210 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ 211 {#ID, TYPE, ATTRS, nullptr, HEADER, ALL_LANGUAGES}, 212 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ 213 {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, 214 #include "clang/Basic/BuiltinsHexagon.inc" 215 }; 216 217 bool HexagonTargetInfo::hasFeature(StringRef Feature) const { 218 std::string VS = "hvxv" + HVXVersion; 219 if (Feature == VS) 220 return true; 221 222 return llvm::StringSwitch<bool>(Feature) 223 .Case("hexagon", true) 224 .Case("hvx", HasHVX) 225 .Case("hvx-length64b", HasHVX64B) 226 .Case("hvx-length128b", HasHVX128B) 227 .Case("long-calls", UseLongCalls) 228 .Case("audio", HasAudio) 229 .Default(false); 230 } 231 232 struct CPUSuffix { 233 llvm::StringLiteral Name; 234 llvm::StringLiteral Suffix; 235 }; 236 237 static constexpr CPUSuffix Suffixes[] = { 238 {{"hexagonv5"}, {"5"}}, {{"hexagonv55"}, {"55"}}, 239 {{"hexagonv60"}, {"60"}}, {{"hexagonv62"}, {"62"}}, 240 {{"hexagonv65"}, {"65"}}, {{"hexagonv66"}, {"66"}}, 241 {{"hexagonv67"}, {"67"}}, {{"hexagonv67t"}, {"67t"}}, 242 {{"hexagonv68"}, {"68"}}, {{"hexagonv69"}, {"69"}}, 243 {{"hexagonv71"}, {"71"}}, {{"hexagonv71t"}, {"71t"}}, 244 {{"hexagonv73"}, {"73"}}, {{"hexagonv75"}, {"75"}}, 245 {{"hexagonv79"}, {"79"}}, 246 }; 247 248 std::optional<unsigned> HexagonTargetInfo::getHexagonCPURev(StringRef Name) { 249 StringRef Arch = Name; 250 Arch.consume_front("hexagonv"); 251 Arch.consume_back("t"); 252 253 unsigned Val; 254 if (!Arch.getAsInteger(0, Val)) 255 return Val; 256 257 return std::nullopt; 258 } 259 260 const char *HexagonTargetInfo::getHexagonCPUSuffix(StringRef Name) { 261 const CPUSuffix *Item = llvm::find_if( 262 Suffixes, [Name](const CPUSuffix &S) { return S.Name == Name; }); 263 if (Item == std::end(Suffixes)) 264 return nullptr; 265 return Item->Suffix.data(); 266 } 267 268 void HexagonTargetInfo::fillValidCPUList( 269 SmallVectorImpl<StringRef> &Values) const { 270 for (const CPUSuffix &Suffix : Suffixes) 271 Values.push_back(Suffix.Name); 272 } 273 274 ArrayRef<Builtin::Info> HexagonTargetInfo::getTargetBuiltins() const { 275 return llvm::ArrayRef(BuiltinInfo, clang::Hexagon::LastTSBuiltin - 276 Builtin::FirstTSBuiltin); 277 } 278