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 } 69 70 if (hasFeature("hvx-length64b")) { 71 Builder.defineMacro("__HVX__"); 72 Builder.defineMacro("__HVX_ARCH__", HVXVersion); 73 Builder.defineMacro("__HVX_LENGTH__", "64"); 74 } 75 76 if (hasFeature("hvx-length128b")) { 77 Builder.defineMacro("__HVX__"); 78 Builder.defineMacro("__HVX_ARCH__", HVXVersion); 79 Builder.defineMacro("__HVX_LENGTH__", "128"); 80 if (DefineHvxDbl) 81 Builder.defineMacro("__HVXDBL__"); 82 } 83 84 if (hasFeature("audio")) { 85 Builder.defineMacro("__HEXAGON_AUDIO__"); 86 } 87 88 std::string NumPhySlots = isTinyCore() ? "3" : "4"; 89 Builder.defineMacro("__HEXAGON_PHYSICAL_SLOTS__", NumPhySlots); 90 } 91 92 bool HexagonTargetInfo::initFeatureMap( 93 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, 94 const std::vector<std::string> &FeaturesVec) const { 95 if (isTinyCore()) 96 Features["audio"] = true; 97 98 StringRef CPUFeature = CPU; 99 CPUFeature.consume_front("hexagon"); 100 CPUFeature.consume_back("t"); 101 if (!CPUFeature.empty()) 102 Features[CPUFeature] = true; 103 104 Features["long-calls"] = false; 105 106 return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); 107 } 108 109 bool HexagonTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 110 DiagnosticsEngine &Diags) { 111 for (auto &F : Features) { 112 if (F == "+hvx-length64b") 113 HasHVX = HasHVX64B = true; 114 else if (F == "+hvx-length128b") 115 HasHVX = HasHVX128B = true; 116 else if (F.find("+hvxv") != std::string::npos) { 117 HasHVX = true; 118 HVXVersion = F.substr(std::string("+hvxv").length()); 119 } else if (F == "-hvx") 120 HasHVX = HasHVX64B = HasHVX128B = false; 121 else if (F == "+long-calls") 122 UseLongCalls = true; 123 else if (F == "-long-calls") 124 UseLongCalls = false; 125 else if (F == "+audio") 126 HasAudio = true; 127 } 128 return true; 129 } 130 131 const char *const HexagonTargetInfo::GCCRegNames[] = { 132 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", 133 "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", 134 "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", 135 "r27", "r28", "r29", "r30", "r31", "p0", "p1", "p2", "p3", 136 "sa0", "lc0", "sa1", "lc1", "m0", "m1", "usr", "ugp", 137 "r1:0", "r3:2", "r5:4", "r7:6", "r9:8", "r11:10", "r13:12", "r15:14", 138 "r17:16", "r19:18", "r21:20", "r23:22", "r25:24", "r27:26", "r29:28", 139 "r31:30" 140 }; 141 142 ArrayRef<const char *> HexagonTargetInfo::getGCCRegNames() const { 143 return llvm::makeArrayRef(GCCRegNames); 144 } 145 146 const TargetInfo::GCCRegAlias HexagonTargetInfo::GCCRegAliases[] = { 147 {{"sp"}, "r29"}, 148 {{"fp"}, "r30"}, 149 {{"lr"}, "r31"}, 150 }; 151 152 ArrayRef<TargetInfo::GCCRegAlias> HexagonTargetInfo::getGCCRegAliases() const { 153 return llvm::makeArrayRef(GCCRegAliases); 154 } 155 156 const Builtin::Info HexagonTargetInfo::BuiltinInfo[] = { 157 #define BUILTIN(ID, TYPE, ATTRS) \ 158 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, 159 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ 160 {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr}, 161 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ 162 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE}, 163 #include "clang/Basic/BuiltinsHexagon.def" 164 }; 165 166 bool HexagonTargetInfo::hasFeature(StringRef Feature) const { 167 std::string VS = "hvxv" + HVXVersion; 168 if (Feature == VS) 169 return true; 170 171 return llvm::StringSwitch<bool>(Feature) 172 .Case("hexagon", true) 173 .Case("hvx", HasHVX) 174 .Case("hvx-length64b", HasHVX64B) 175 .Case("hvx-length128b", HasHVX128B) 176 .Case("long-calls", UseLongCalls) 177 .Case("audio", HasAudio) 178 .Default(false); 179 } 180 181 struct CPUSuffix { 182 llvm::StringLiteral Name; 183 llvm::StringLiteral Suffix; 184 }; 185 186 static constexpr CPUSuffix Suffixes[] = { 187 {{"hexagonv5"}, {"5"}}, {{"hexagonv55"}, {"55"}}, 188 {{"hexagonv60"}, {"60"}}, {{"hexagonv62"}, {"62"}}, 189 {{"hexagonv65"}, {"65"}}, {{"hexagonv66"}, {"66"}}, 190 {{"hexagonv67"}, {"67"}}, {{"hexagonv67t"}, {"67t"}}, 191 }; 192 193 const char *HexagonTargetInfo::getHexagonCPUSuffix(StringRef Name) { 194 const CPUSuffix *Item = llvm::find_if( 195 Suffixes, [Name](const CPUSuffix &S) { return S.Name == Name; }); 196 if (Item == std::end(Suffixes)) 197 return nullptr; 198 return Item->Suffix.data(); 199 } 200 201 void HexagonTargetInfo::fillValidCPUList( 202 SmallVectorImpl<StringRef> &Values) const { 203 for (const CPUSuffix &Suffix : Suffixes) 204 Values.push_back(Suffix.Name); 205 } 206 207 ArrayRef<Builtin::Info> HexagonTargetInfo::getTargetBuiltins() const { 208 return llvm::makeArrayRef(BuiltinInfo, clang::Hexagon::LastTSBuiltin - 209 Builtin::FirstTSBuiltin); 210 } 211