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