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