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