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 85*81ad6265SDimitry Andric std::string convertConstraint(const char *&Constraint) const override { 86*81ad6265SDimitry Andric switch (Constraint[0]) { 87*81ad6265SDimitry Andric case 'p': // Keep 'p' constraint. 88*81ad6265SDimitry Andric return std::string("p"); 89*81ad6265SDimitry Andric case 'Z': 90*81ad6265SDimitry Andric switch (Constraint[1]) { 91*81ad6265SDimitry Andric case 'Q': // Address with base and unsigned 12-bit displacement 92*81ad6265SDimitry Andric case 'R': // Likewise, plus an index 93*81ad6265SDimitry Andric case 'S': // Address with base and signed 20-bit displacement 94*81ad6265SDimitry Andric case 'T': // Likewise, plus an index 95*81ad6265SDimitry Andric // "^" hints llvm that this is a 2 letter constraint. 96*81ad6265SDimitry Andric // "Constraint++" is used to promote the string iterator 97*81ad6265SDimitry Andric // to the next constraint. 98*81ad6265SDimitry Andric return std::string("^") + std::string(Constraint++, 2); 99*81ad6265SDimitry Andric default: 100*81ad6265SDimitry Andric break; 101*81ad6265SDimitry Andric } 102*81ad6265SDimitry Andric break; 103*81ad6265SDimitry Andric default: 104*81ad6265SDimitry Andric break; 105*81ad6265SDimitry Andric } 106*81ad6265SDimitry Andric return TargetInfo::convertConstraint(Constraint); 107*81ad6265SDimitry Andric } 108*81ad6265SDimitry Andric 1090b57cec5SDimitry Andric const char *getClobbers() const override { 1100b57cec5SDimitry Andric // FIXME: Is this really right? 1110b57cec5SDimitry Andric return ""; 1120b57cec5SDimitry Andric } 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric BuiltinVaListKind getBuiltinVaListKind() const override { 1150b57cec5SDimitry Andric return TargetInfo::SystemZBuiltinVaList; 1160b57cec5SDimitry Andric } 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric int getISARevision(StringRef Name) const; 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric bool isValidCPUName(StringRef Name) const override { 1210b57cec5SDimitry Andric return getISARevision(Name) != -1; 1220b57cec5SDimitry Andric } 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric bool setCPU(const std::string &Name) override { 1270b57cec5SDimitry Andric CPU = Name; 1280b57cec5SDimitry Andric ISARevision = getISARevision(CPU); 1290b57cec5SDimitry Andric return ISARevision != -1; 1300b57cec5SDimitry Andric } 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric bool 1330b57cec5SDimitry Andric initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, 1340b57cec5SDimitry Andric StringRef CPU, 1350b57cec5SDimitry Andric const std::vector<std::string> &FeaturesVec) const override { 1360b57cec5SDimitry Andric int ISARevision = getISARevision(CPU); 1370b57cec5SDimitry Andric if (ISARevision >= 10) 1380b57cec5SDimitry Andric Features["transactional-execution"] = true; 1390b57cec5SDimitry Andric if (ISARevision >= 11) 1400b57cec5SDimitry Andric Features["vector"] = true; 1410b57cec5SDimitry Andric if (ISARevision >= 12) 1420b57cec5SDimitry Andric Features["vector-enhancements-1"] = true; 1430b57cec5SDimitry Andric if (ISARevision >= 13) 1440b57cec5SDimitry Andric Features["vector-enhancements-2"] = true; 145fe6060f1SDimitry Andric if (ISARevision >= 14) 146fe6060f1SDimitry Andric Features["nnp-assist"] = true; 1470b57cec5SDimitry Andric return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric bool handleTargetFeatures(std::vector<std::string> &Features, 1510b57cec5SDimitry Andric DiagnosticsEngine &Diags) override { 1520b57cec5SDimitry Andric HasTransactionalExecution = false; 1530b57cec5SDimitry Andric HasVector = false; 1545ffd83dbSDimitry Andric SoftFloat = false; 1550b57cec5SDimitry Andric for (const auto &Feature : Features) { 1560b57cec5SDimitry Andric if (Feature == "+transactional-execution") 1570b57cec5SDimitry Andric HasTransactionalExecution = true; 1580b57cec5SDimitry Andric else if (Feature == "+vector") 1590b57cec5SDimitry Andric HasVector = true; 1605ffd83dbSDimitry Andric else if (Feature == "+soft-float") 1615ffd83dbSDimitry Andric SoftFloat = true; 1620b57cec5SDimitry Andric } 1635ffd83dbSDimitry Andric HasVector &= !SoftFloat; 1645ffd83dbSDimitry Andric 1650b57cec5SDimitry Andric // If we use the vector ABI, vector types are 64-bit aligned. 166349cc55cSDimitry Andric if (HasVector && !getTriple().isOSzOS()) { 1670b57cec5SDimitry Andric MaxVectorAlign = 64; 1680b57cec5SDimitry Andric resetDataLayout("E-m:e-i1:8:16-i8:8:16-i64:64-f128:64" 1690b57cec5SDimitry Andric "-v128:64-a:8:16-n32:64"); 1700b57cec5SDimitry Andric } 1710b57cec5SDimitry Andric return true; 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric bool hasFeature(StringRef Feature) const override; 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { 1770b57cec5SDimitry Andric switch (CC) { 1780b57cec5SDimitry Andric case CC_C: 1790b57cec5SDimitry Andric case CC_Swift: 1800b57cec5SDimitry Andric case CC_OpenCLKernel: 1810b57cec5SDimitry Andric return CCCR_OK; 182fe6060f1SDimitry Andric case CC_SwiftAsync: 183fe6060f1SDimitry Andric return CCCR_Error; 1840b57cec5SDimitry Andric default: 1850b57cec5SDimitry Andric return CCCR_Warning; 1860b57cec5SDimitry Andric } 1870b57cec5SDimitry Andric } 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric StringRef getABI() const override { 1900b57cec5SDimitry Andric if (HasVector) 1910b57cec5SDimitry Andric return "vector"; 1920b57cec5SDimitry Andric return ""; 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric const char *getLongDoubleMangling() const override { return "g"; } 1965ffd83dbSDimitry Andric 1970eae32dcSDimitry Andric bool hasBitIntType() const override { return true; } 198e8d8bef9SDimitry Andric 199e8d8bef9SDimitry Andric int getEHDataRegisterNumber(unsigned RegNo) const override { 200e8d8bef9SDimitry Andric return RegNo < 4 ? 6 + RegNo : -1; 201e8d8bef9SDimitry Andric } 2020b57cec5SDimitry Andric }; 2030b57cec5SDimitry Andric } // namespace targets 2040b57cec5SDimitry Andric } // namespace clang 2050b57cec5SDimitry Andric #endif // LLVM_CLANG_LIB_BASIC_TARGETS_SYSTEMZ_H 206