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