10b57cec5SDimitry Andric //===--- SystemZ.h - Declare SystemZ 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 SystemZ TargetInfo objects. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_SYSTEMZ_H 140b57cec5SDimitry Andric #define LLVM_CLANG_LIB_BASIC_TARGETS_SYSTEMZ_H 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h" 170b57cec5SDimitry Andric #include "clang/Basic/TargetOptions.h" 180b57cec5SDimitry Andric #include "llvm/ADT/Triple.h" 190b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric namespace clang { 220b57cec5SDimitry Andric namespace targets { 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo { 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric static const Builtin::Info BuiltinInfo[]; 270b57cec5SDimitry Andric static const char *const GCCRegNames[]; 280b57cec5SDimitry Andric std::string CPU; 290b57cec5SDimitry Andric int ISARevision; 300b57cec5SDimitry Andric bool HasTransactionalExecution; 310b57cec5SDimitry Andric bool HasVector; 325ffd83dbSDimitry Andric bool SoftFloat; 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric public: 350b57cec5SDimitry Andric SystemZTargetInfo(const llvm::Triple &Triple, const TargetOptions &) 360b57cec5SDimitry Andric : TargetInfo(Triple), CPU("z10"), ISARevision(8), 375ffd83dbSDimitry Andric HasTransactionalExecution(false), HasVector(false), SoftFloat(false) { 380b57cec5SDimitry Andric IntMaxType = SignedLong; 390b57cec5SDimitry Andric Int64Type = SignedLong; 400b57cec5SDimitry Andric TLSSupported = true; 410b57cec5SDimitry Andric IntWidth = IntAlign = 32; 420b57cec5SDimitry Andric LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64; 430b57cec5SDimitry Andric PointerWidth = PointerAlign = 64; 440b57cec5SDimitry Andric LongDoubleWidth = 128; 450b57cec5SDimitry Andric LongDoubleAlign = 64; 460b57cec5SDimitry Andric LongDoubleFormat = &llvm::APFloat::IEEEquad(); 470b57cec5SDimitry Andric DefaultAlignForAttributeAligned = 64; 480b57cec5SDimitry Andric MinGlobalAlign = 16; 49349cc55cSDimitry Andric if (Triple.isOSzOS()) { 50349cc55cSDimitry Andric // All vector types are default aligned on an 8-byte boundary, even if the 51349cc55cSDimitry Andric // vector facility is not available. That is different from Linux. 52349cc55cSDimitry Andric MaxVectorAlign = 64; 53349cc55cSDimitry Andric // Compared to Linux/ELF, the data layout differs only in some details: 54349cc55cSDimitry Andric // - name mangling is GOFF 55349cc55cSDimitry Andric // - 128 bit vector types are 64 bit aligned 56349cc55cSDimitry Andric resetDataLayout( 57349cc55cSDimitry Andric "E-m:l-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64"); 58349cc55cSDimitry Andric } else 590b57cec5SDimitry Andric resetDataLayout("E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64"); 600b57cec5SDimitry Andric MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; 615ffd83dbSDimitry Andric HasStrictFP = true; 620b57cec5SDimitry Andric } 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric void getTargetDefines(const LangOptions &Opts, 650b57cec5SDimitry Andric MacroBuilder &Builder) const override; 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric ArrayRef<Builtin::Info> getTargetBuiltins() const override; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric ArrayRef<const char *> getGCCRegNames() const override; 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { 720b57cec5SDimitry Andric // No aliases. 730b57cec5SDimitry Andric return None; 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override; 770b57cec5SDimitry Andric 785ffd83dbSDimitry Andric bool isSPRegName(StringRef RegName) const override { 795ffd83dbSDimitry Andric return RegName.equals("r15"); 805ffd83dbSDimitry Andric } 815ffd83dbSDimitry Andric 820b57cec5SDimitry Andric bool validateAsmConstraint(const char *&Name, 830b57cec5SDimitry Andric TargetInfo::ConstraintInfo &info) const override; 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric const char *getClobbers() const override { 860b57cec5SDimitry Andric // FIXME: Is this really right? 870b57cec5SDimitry Andric return ""; 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric BuiltinVaListKind getBuiltinVaListKind() const override { 910b57cec5SDimitry Andric return TargetInfo::SystemZBuiltinVaList; 920b57cec5SDimitry Andric } 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric int getISARevision(StringRef Name) const; 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric bool isValidCPUName(StringRef Name) const override { 970b57cec5SDimitry Andric return getISARevision(Name) != -1; 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric bool setCPU(const std::string &Name) override { 1030b57cec5SDimitry Andric CPU = Name; 1040b57cec5SDimitry Andric ISARevision = getISARevision(CPU); 1050b57cec5SDimitry Andric return ISARevision != -1; 1060b57cec5SDimitry Andric } 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric bool 1090b57cec5SDimitry Andric initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, 1100b57cec5SDimitry Andric StringRef CPU, 1110b57cec5SDimitry Andric const std::vector<std::string> &FeaturesVec) const override { 1120b57cec5SDimitry Andric int ISARevision = getISARevision(CPU); 1130b57cec5SDimitry Andric if (ISARevision >= 10) 1140b57cec5SDimitry Andric Features["transactional-execution"] = true; 1150b57cec5SDimitry Andric if (ISARevision >= 11) 1160b57cec5SDimitry Andric Features["vector"] = true; 1170b57cec5SDimitry Andric if (ISARevision >= 12) 1180b57cec5SDimitry Andric Features["vector-enhancements-1"] = true; 1190b57cec5SDimitry Andric if (ISARevision >= 13) 1200b57cec5SDimitry Andric Features["vector-enhancements-2"] = true; 121fe6060f1SDimitry Andric if (ISARevision >= 14) 122fe6060f1SDimitry Andric Features["nnp-assist"] = true; 1230b57cec5SDimitry Andric return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); 1240b57cec5SDimitry Andric } 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric bool handleTargetFeatures(std::vector<std::string> &Features, 1270b57cec5SDimitry Andric DiagnosticsEngine &Diags) override { 1280b57cec5SDimitry Andric HasTransactionalExecution = false; 1290b57cec5SDimitry Andric HasVector = false; 1305ffd83dbSDimitry Andric SoftFloat = false; 1310b57cec5SDimitry Andric for (const auto &Feature : Features) { 1320b57cec5SDimitry Andric if (Feature == "+transactional-execution") 1330b57cec5SDimitry Andric HasTransactionalExecution = true; 1340b57cec5SDimitry Andric else if (Feature == "+vector") 1350b57cec5SDimitry Andric HasVector = true; 1365ffd83dbSDimitry Andric else if (Feature == "+soft-float") 1375ffd83dbSDimitry Andric SoftFloat = true; 1380b57cec5SDimitry Andric } 1395ffd83dbSDimitry Andric HasVector &= !SoftFloat; 1405ffd83dbSDimitry Andric 1410b57cec5SDimitry Andric // If we use the vector ABI, vector types are 64-bit aligned. 142349cc55cSDimitry Andric if (HasVector && !getTriple().isOSzOS()) { 1430b57cec5SDimitry Andric MaxVectorAlign = 64; 1440b57cec5SDimitry Andric resetDataLayout("E-m:e-i1:8:16-i8:8:16-i64:64-f128:64" 1450b57cec5SDimitry Andric "-v128:64-a:8:16-n32:64"); 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric return true; 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric bool hasFeature(StringRef Feature) const override; 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { 1530b57cec5SDimitry Andric switch (CC) { 1540b57cec5SDimitry Andric case CC_C: 1550b57cec5SDimitry Andric case CC_Swift: 1560b57cec5SDimitry Andric case CC_OpenCLKernel: 1570b57cec5SDimitry Andric return CCCR_OK; 158fe6060f1SDimitry Andric case CC_SwiftAsync: 159fe6060f1SDimitry Andric return CCCR_Error; 1600b57cec5SDimitry Andric default: 1610b57cec5SDimitry Andric return CCCR_Warning; 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric } 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric StringRef getABI() const override { 1660b57cec5SDimitry Andric if (HasVector) 1670b57cec5SDimitry Andric return "vector"; 1680b57cec5SDimitry Andric return ""; 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric const char *getLongDoubleMangling() const override { return "g"; } 1725ffd83dbSDimitry Andric 173*0eae32dcSDimitry Andric bool hasBitIntType() const override { return true; } 174e8d8bef9SDimitry Andric 175e8d8bef9SDimitry Andric int getEHDataRegisterNumber(unsigned RegNo) const override { 176e8d8bef9SDimitry Andric return RegNo < 4 ? 6 + RegNo : -1; 177e8d8bef9SDimitry Andric } 1780b57cec5SDimitry Andric }; 1790b57cec5SDimitry Andric } // namespace targets 1800b57cec5SDimitry Andric } // namespace clang 1810b57cec5SDimitry Andric #endif // LLVM_CLANG_LIB_BASIC_TARGETS_SYSTEMZ_H 182