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