|  | //===--- Hexagon.cpp - Implement Hexagon target feature support -----------===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // This file implements Hexagon TargetInfo objects. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "Hexagon.h" | 
|  | #include "Targets.h" | 
|  | #include "clang/Basic/MacroBuilder.h" | 
|  | #include "clang/Basic/TargetBuiltins.h" | 
|  | #include "llvm/ADT/StringSwitch.h" | 
|  |  | 
|  | using namespace clang; | 
|  | using namespace clang::targets; | 
|  |  | 
|  | void HexagonTargetInfo::getTargetDefines(const LangOptions &Opts, | 
|  | MacroBuilder &Builder) const { | 
|  | Builder.defineMacro("__qdsp6__", "1"); | 
|  | Builder.defineMacro("__hexagon__", "1"); | 
|  |  | 
|  | if (CPU == "hexagonv5") { | 
|  | Builder.defineMacro("__HEXAGON_V5__"); | 
|  | Builder.defineMacro("__HEXAGON_ARCH__", "5"); | 
|  | if (Opts.HexagonQdsp6Compat) { | 
|  | Builder.defineMacro("__QDSP6_V5__"); | 
|  | Builder.defineMacro("__QDSP6_ARCH__", "5"); | 
|  | } | 
|  | } else if (CPU == "hexagonv55") { | 
|  | Builder.defineMacro("__HEXAGON_V55__"); | 
|  | Builder.defineMacro("__HEXAGON_ARCH__", "55"); | 
|  | Builder.defineMacro("__QDSP6_V55__"); | 
|  | Builder.defineMacro("__QDSP6_ARCH__", "55"); | 
|  | } else if (CPU == "hexagonv60") { | 
|  | Builder.defineMacro("__HEXAGON_V60__"); | 
|  | Builder.defineMacro("__HEXAGON_ARCH__", "60"); | 
|  | Builder.defineMacro("__QDSP6_V60__"); | 
|  | Builder.defineMacro("__QDSP6_ARCH__", "60"); | 
|  | } else if (CPU == "hexagonv62") { | 
|  | Builder.defineMacro("__HEXAGON_V62__"); | 
|  | Builder.defineMacro("__HEXAGON_ARCH__", "62"); | 
|  | } else if (CPU == "hexagonv65") { | 
|  | Builder.defineMacro("__HEXAGON_V65__"); | 
|  | Builder.defineMacro("__HEXAGON_ARCH__", "65"); | 
|  | } else if (CPU == "hexagonv66") { | 
|  | Builder.defineMacro("__HEXAGON_V66__"); | 
|  | Builder.defineMacro("__HEXAGON_ARCH__", "66"); | 
|  | } | 
|  |  | 
|  | if (hasFeature("hvx-length64b")) { | 
|  | Builder.defineMacro("__HVX__"); | 
|  | Builder.defineMacro("__HVX_ARCH__", HVXVersion); | 
|  | Builder.defineMacro("__HVX_LENGTH__", "64"); | 
|  | } | 
|  |  | 
|  | if (hasFeature("hvx-length128b")) { | 
|  | Builder.defineMacro("__HVX__"); | 
|  | Builder.defineMacro("__HVX_ARCH__", HVXVersion); | 
|  | Builder.defineMacro("__HVX_LENGTH__", "128"); | 
|  | // FIXME: This macro is deprecated. | 
|  | Builder.defineMacro("__HVXDBL__"); | 
|  | } | 
|  | } | 
|  |  | 
|  | bool HexagonTargetInfo::initFeatureMap( | 
|  | llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, | 
|  | const std::vector<std::string> &FeaturesVec) const { | 
|  | Features["long-calls"] = false; | 
|  |  | 
|  | return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); | 
|  | } | 
|  |  | 
|  | bool HexagonTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, | 
|  | DiagnosticsEngine &Diags) { | 
|  | for (auto &F : Features) { | 
|  | if (F == "+hvx-length64b") | 
|  | HasHVX = HasHVX64B = true; | 
|  | else if (F == "+hvx-length128b") | 
|  | HasHVX = HasHVX128B = true; | 
|  | else if (F.find("+hvxv") != std::string::npos) { | 
|  | HasHVX = true; | 
|  | HVXVersion = F.substr(std::string("+hvxv").length()); | 
|  | } else if (F == "-hvx") | 
|  | HasHVX = HasHVX64B = HasHVX128B = false; | 
|  | else if (F == "+long-calls") | 
|  | UseLongCalls = true; | 
|  | else if (F == "-long-calls") | 
|  | UseLongCalls = false; | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | const char *const HexagonTargetInfo::GCCRegNames[] = { | 
|  | "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",  "r8", | 
|  | "r9",  "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", | 
|  | "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", | 
|  | "r27", "r28", "r29", "r30", "r31", "p0",  "p1",  "p2",  "p3", | 
|  | "sa0", "lc0", "sa1", "lc1", "m0",  "m1",  "usr", "ugp" | 
|  | }; | 
|  |  | 
|  | ArrayRef<const char *> HexagonTargetInfo::getGCCRegNames() const { | 
|  | return llvm::makeArrayRef(GCCRegNames); | 
|  | } | 
|  |  | 
|  | const TargetInfo::GCCRegAlias HexagonTargetInfo::GCCRegAliases[] = { | 
|  | {{"sp"}, "r29"}, | 
|  | {{"fp"}, "r30"}, | 
|  | {{"lr"}, "r31"}, | 
|  | }; | 
|  |  | 
|  | ArrayRef<TargetInfo::GCCRegAlias> HexagonTargetInfo::getGCCRegAliases() const { | 
|  | return llvm::makeArrayRef(GCCRegAliases); | 
|  | } | 
|  |  | 
|  | const Builtin::Info HexagonTargetInfo::BuiltinInfo[] = { | 
|  | #define BUILTIN(ID, TYPE, ATTRS)                                               \ | 
|  | {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, | 
|  | #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER)                                    \ | 
|  | {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr}, | 
|  | #include "clang/Basic/BuiltinsHexagon.def" | 
|  | }; | 
|  |  | 
|  | bool HexagonTargetInfo::hasFeature(StringRef Feature) const { | 
|  | std::string VS = "hvxv" + HVXVersion; | 
|  | if (Feature == VS) | 
|  | return true; | 
|  |  | 
|  | return llvm::StringSwitch<bool>(Feature) | 
|  | .Case("hexagon", true) | 
|  | .Case("hvx", HasHVX) | 
|  | .Case("hvx-length64b", HasHVX64B) | 
|  | .Case("hvx-length128b", HasHVX128B) | 
|  | .Case("long-calls", UseLongCalls) | 
|  | .Default(false); | 
|  | } | 
|  |  | 
|  | struct CPUSuffix { | 
|  | llvm::StringLiteral Name; | 
|  | llvm::StringLiteral Suffix; | 
|  | }; | 
|  |  | 
|  | static constexpr CPUSuffix Suffixes[] = { | 
|  | {{"hexagonv5"},  {"5"}},  {{"hexagonv55"}, {"55"}}, | 
|  | {{"hexagonv60"}, {"60"}}, {{"hexagonv62"}, {"62"}}, | 
|  | {{"hexagonv65"}, {"65"}}, {{"hexagonv66"}, {"66"}}, | 
|  | }; | 
|  |  | 
|  | const char *HexagonTargetInfo::getHexagonCPUSuffix(StringRef Name) { | 
|  | const CPUSuffix *Item = llvm::find_if( | 
|  | Suffixes, [Name](const CPUSuffix &S) { return S.Name == Name; }); | 
|  | if (Item == std::end(Suffixes)) | 
|  | return nullptr; | 
|  | return Item->Suffix.data(); | 
|  | } | 
|  |  | 
|  | void HexagonTargetInfo::fillValidCPUList( | 
|  | SmallVectorImpl<StringRef> &Values) const { | 
|  | for (const CPUSuffix &Suffix : Suffixes) | 
|  | Values.push_back(Suffix.Name); | 
|  | } | 
|  |  | 
|  | ArrayRef<Builtin::Info> HexagonTargetInfo::getTargetBuiltins() const { | 
|  | return llvm::makeArrayRef(BuiltinInfo, clang::Hexagon::LastTSBuiltin - | 
|  | Builtin::FirstTSBuiltin); | 
|  | } |