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