10b57cec5SDimitry Andric //===--- Hexagon.h - Declare Hexagon target feature support -----*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file declares Hexagon TargetInfo objects. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_HEXAGON_H 140b57cec5SDimitry Andric #define LLVM_CLANG_LIB_BASIC_TARGETS_HEXAGON_H 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h" 170b57cec5SDimitry Andric #include "clang/Basic/TargetOptions.h" 180b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 1906c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 20*0fca6ea1SDimitry Andric #include <optional> 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric namespace clang { 230b57cec5SDimitry Andric namespace targets { 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric // Hexagon abstract base class 260b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY HexagonTargetInfo : public TargetInfo { 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric static const char *const GCCRegNames[]; 290b57cec5SDimitry Andric static const TargetInfo::GCCRegAlias GCCRegAliases[]; 300b57cec5SDimitry Andric std::string CPU; 310b57cec5SDimitry Andric std::string HVXVersion; 320b57cec5SDimitry Andric bool HasHVX = false; 330b57cec5SDimitry Andric bool HasHVX64B = false; 340b57cec5SDimitry Andric bool HasHVX128B = false; 355ffd83dbSDimitry Andric bool HasAudio = false; 360b57cec5SDimitry Andric bool UseLongCalls = false; 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric public: HexagonTargetInfo(const llvm::Triple & Triple,const TargetOptions &)390b57cec5SDimitry Andric HexagonTargetInfo(const llvm::Triple &Triple, const TargetOptions &) 400b57cec5SDimitry Andric : TargetInfo(Triple) { 410b57cec5SDimitry Andric // Specify the vector alignment explicitly. For v512x1, the calculated 420b57cec5SDimitry Andric // alignment would be 512*alignment(i1), which is 512 bytes, instead of 430b57cec5SDimitry Andric // the required minimum of 64 bytes. 440b57cec5SDimitry Andric resetDataLayout( 450b57cec5SDimitry Andric "e-m:e-p:32:32:32-a:0-n16:32-" 460b57cec5SDimitry Andric "i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-" 470b57cec5SDimitry Andric "v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048"); 480b57cec5SDimitry Andric SizeType = UnsignedInt; 490b57cec5SDimitry Andric PtrDiffType = SignedInt; 500b57cec5SDimitry Andric IntPtrType = SignedInt; 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric // {} in inline assembly are packet specifiers, not assembly variant 530b57cec5SDimitry Andric // specifiers. 540b57cec5SDimitry Andric NoAsmVariants = true; 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric LargeArrayMinWidth = 64; 570b57cec5SDimitry Andric LargeArrayAlign = 64; 580b57cec5SDimitry Andric UseBitFieldTypeAlignment = true; 590b57cec5SDimitry Andric ZeroLengthBitfieldBoundary = 32; 605ffd83dbSDimitry Andric MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; 615ffd83dbSDimitry Andric 625ffd83dbSDimitry Andric // These are the default values anyway, but explicitly make sure 635ffd83dbSDimitry Andric // that the size of the boolean type is 8 bits. Bool vectors are used 645ffd83dbSDimitry Andric // for modeling predicate registers in HVX, and the bool -> byte 655ffd83dbSDimitry Andric // correspondence matches the HVX architecture. 665ffd83dbSDimitry Andric BoolWidth = BoolAlign = 8; 670b57cec5SDimitry Andric } 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric ArrayRef<Builtin::Info> getTargetBuiltins() const override; 700b57cec5SDimitry Andric validateAsmConstraint(const char * & Name,TargetInfo::ConstraintInfo & Info)710b57cec5SDimitry Andric bool validateAsmConstraint(const char *&Name, 720b57cec5SDimitry Andric TargetInfo::ConstraintInfo &Info) const override { 730b57cec5SDimitry Andric switch (*Name) { 740b57cec5SDimitry Andric case 'v': 750b57cec5SDimitry Andric case 'q': 760b57cec5SDimitry Andric if (HasHVX) { 770b57cec5SDimitry Andric Info.setAllowsRegister(); 780b57cec5SDimitry Andric return true; 790b57cec5SDimitry Andric } 800b57cec5SDimitry Andric break; 810b57cec5SDimitry Andric case 'a': // Modifier register m0-m1. 820b57cec5SDimitry Andric Info.setAllowsRegister(); 830b57cec5SDimitry Andric return true; 840b57cec5SDimitry Andric case 's': 850b57cec5SDimitry Andric // Relocatable constant. 860b57cec5SDimitry Andric return true; 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric return false; 890b57cec5SDimitry Andric } 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric void getTargetDefines(const LangOptions &Opts, 920b57cec5SDimitry Andric MacroBuilder &Builder) const override; 930b57cec5SDimitry Andric isCLZForZeroUndef()940b57cec5SDimitry Andric bool isCLZForZeroUndef() const override { return false; } 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric bool hasFeature(StringRef Feature) const override; 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric bool 990b57cec5SDimitry Andric initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, 1000b57cec5SDimitry Andric StringRef CPU, 1010b57cec5SDimitry Andric const std::vector<std::string> &FeaturesVec) const override; 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric bool handleTargetFeatures(std::vector<std::string> &Features, 1040b57cec5SDimitry Andric DiagnosticsEngine &Diags) override; 1050b57cec5SDimitry Andric getBuiltinVaListKind()1060b57cec5SDimitry Andric BuiltinVaListKind getBuiltinVaListKind() const override { 1075ffd83dbSDimitry Andric if (getTriple().isMusl()) 1085ffd83dbSDimitry Andric return TargetInfo::HexagonBuiltinVaList; 1090b57cec5SDimitry Andric return TargetInfo::CharPtrBuiltinVaList; 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric ArrayRef<const char *> getGCCRegNames() const override; 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override; 1150b57cec5SDimitry Andric getClobbers()11606c3fb27SDimitry Andric std::string_view getClobbers() const override { return ""; } 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric static const char *getHexagonCPUSuffix(StringRef Name); 119*0fca6ea1SDimitry Andric static std::optional<unsigned> getHexagonCPURev(StringRef Name); 1200b57cec5SDimitry Andric isValidCPUName(StringRef Name)1210b57cec5SDimitry Andric bool isValidCPUName(StringRef Name) const override { 1220b57cec5SDimitry Andric return getHexagonCPUSuffix(Name); 1230b57cec5SDimitry Andric } 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; 1260b57cec5SDimitry Andric setCPU(const std::string & Name)1270b57cec5SDimitry Andric bool setCPU(const std::string &Name) override { 1280b57cec5SDimitry Andric if (!isValidCPUName(Name)) 1290b57cec5SDimitry Andric return false; 1300b57cec5SDimitry Andric CPU = Name; 1310b57cec5SDimitry Andric return true; 1320b57cec5SDimitry Andric } 1330b57cec5SDimitry Andric getEHDataRegisterNumber(unsigned RegNo)1340b57cec5SDimitry Andric int getEHDataRegisterNumber(unsigned RegNo) const override { 1350b57cec5SDimitry Andric return RegNo < 2 ? RegNo : -1; 1360b57cec5SDimitry Andric } 1375ffd83dbSDimitry Andric isTinyCore()1385ffd83dbSDimitry Andric bool isTinyCore() const { 1395ffd83dbSDimitry Andric // We can write more stricter checks later. 1405ffd83dbSDimitry Andric return CPU.find('t') != std::string::npos; 1415ffd83dbSDimitry Andric } 1425ffd83dbSDimitry Andric hasBitIntType()1430eae32dcSDimitry Andric bool hasBitIntType() const override { return true; } 144*0fca6ea1SDimitry Andric hardwareInterferenceSizes()145*0fca6ea1SDimitry Andric std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override { 146*0fca6ea1SDimitry Andric std::optional<unsigned> Rev = getHexagonCPURev(CPU); 147*0fca6ea1SDimitry Andric 148*0fca6ea1SDimitry Andric // V73 and later have 64-byte cache lines. 149*0fca6ea1SDimitry Andric unsigned CacheLineSizeBytes = Rev >= 73U ? 64 : 32; 150*0fca6ea1SDimitry Andric return std::make_pair(CacheLineSizeBytes, CacheLineSizeBytes); 151*0fca6ea1SDimitry Andric } 1520b57cec5SDimitry Andric }; 1530b57cec5SDimitry Andric } // namespace targets 1540b57cec5SDimitry Andric } // namespace clang 1550b57cec5SDimitry Andric #endif // LLVM_CLANG_LIB_BASIC_TARGETS_HEXAGON_H 156