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/Support/Compiler.h" 19*06c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.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 char *const GCCRegNames[]; 270b57cec5SDimitry Andric std::string CPU; 280b57cec5SDimitry Andric int ISARevision; 290b57cec5SDimitry Andric bool HasTransactionalExecution; 300b57cec5SDimitry Andric bool HasVector; 315ffd83dbSDimitry Andric bool SoftFloat; 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric public: 340b57cec5SDimitry Andric SystemZTargetInfo(const llvm::Triple &Triple, const TargetOptions &) 350b57cec5SDimitry Andric : TargetInfo(Triple), CPU("z10"), ISARevision(8), 365ffd83dbSDimitry Andric HasTransactionalExecution(false), HasVector(false), SoftFloat(false) { 370b57cec5SDimitry Andric IntMaxType = SignedLong; 380b57cec5SDimitry Andric Int64Type = SignedLong; 390b57cec5SDimitry Andric IntWidth = IntAlign = 32; 400b57cec5SDimitry Andric LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64; 41bdd1243dSDimitry Andric Int128Align = 64; 420b57cec5SDimitry Andric PointerWidth = PointerAlign = 64; 430b57cec5SDimitry Andric LongDoubleWidth = 128; 440b57cec5SDimitry Andric LongDoubleAlign = 64; 450b57cec5SDimitry Andric LongDoubleFormat = &llvm::APFloat::IEEEquad(); 460b57cec5SDimitry Andric DefaultAlignForAttributeAligned = 64; 470b57cec5SDimitry Andric MinGlobalAlign = 16; 48349cc55cSDimitry Andric if (Triple.isOSzOS()) { 49*06c3fb27SDimitry Andric TLSSupported = false; 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; 53*06c3fb27SDimitry Andric // Compared to Linux/ELF, the data layout differs only in some details: 54*06c3fb27SDimitry Andric // - name mangling is GOFF. 55*06c3fb27SDimitry Andric // - 32 bit pointers, either as default or special address space 56*06c3fb27SDimitry Andric resetDataLayout("E-m:l-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-" 57*06c3fb27SDimitry Andric "a:8:16-n32:64"); 58*06c3fb27SDimitry Andric } else { 59*06c3fb27SDimitry Andric TLSSupported = true; 60bdd1243dSDimitry Andric resetDataLayout("E-m:e-i1:8:16-i8:8:16-i64:64-f128:64" 61bdd1243dSDimitry Andric "-v128:64-a:8:16-n32:64"); 62*06c3fb27SDimitry Andric } 630b57cec5SDimitry Andric MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; 645ffd83dbSDimitry Andric HasStrictFP = true; 650b57cec5SDimitry Andric } 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric void getTargetDefines(const LangOptions &Opts, 680b57cec5SDimitry Andric MacroBuilder &Builder) const override; 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric ArrayRef<Builtin::Info> getTargetBuiltins() const override; 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric ArrayRef<const char *> getGCCRegNames() const override; 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { 750b57cec5SDimitry Andric // No aliases. 76bdd1243dSDimitry Andric return std::nullopt; 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override; 800b57cec5SDimitry Andric 815ffd83dbSDimitry Andric bool isSPRegName(StringRef RegName) const override { 825ffd83dbSDimitry Andric return RegName.equals("r15"); 835ffd83dbSDimitry Andric } 845ffd83dbSDimitry Andric 850b57cec5SDimitry Andric bool validateAsmConstraint(const char *&Name, 860b57cec5SDimitry Andric TargetInfo::ConstraintInfo &info) const override; 870b57cec5SDimitry Andric 8881ad6265SDimitry Andric std::string convertConstraint(const char *&Constraint) const override { 8981ad6265SDimitry Andric switch (Constraint[0]) { 9081ad6265SDimitry Andric case 'p': // Keep 'p' constraint. 9181ad6265SDimitry Andric return std::string("p"); 9281ad6265SDimitry Andric case 'Z': 9381ad6265SDimitry Andric switch (Constraint[1]) { 9481ad6265SDimitry Andric case 'Q': // Address with base and unsigned 12-bit displacement 9581ad6265SDimitry Andric case 'R': // Likewise, plus an index 9681ad6265SDimitry Andric case 'S': // Address with base and signed 20-bit displacement 9781ad6265SDimitry Andric case 'T': // Likewise, plus an index 9881ad6265SDimitry Andric // "^" hints llvm that this is a 2 letter constraint. 9981ad6265SDimitry Andric // "Constraint++" is used to promote the string iterator 10081ad6265SDimitry Andric // to the next constraint. 10181ad6265SDimitry Andric return std::string("^") + std::string(Constraint++, 2); 10281ad6265SDimitry Andric default: 10381ad6265SDimitry Andric break; 10481ad6265SDimitry Andric } 10581ad6265SDimitry Andric break; 10681ad6265SDimitry Andric default: 10781ad6265SDimitry Andric break; 10881ad6265SDimitry Andric } 10981ad6265SDimitry Andric return TargetInfo::convertConstraint(Constraint); 11081ad6265SDimitry Andric } 11181ad6265SDimitry Andric 112*06c3fb27SDimitry Andric std::string_view getClobbers() const override { 1130b57cec5SDimitry Andric // FIXME: Is this really right? 1140b57cec5SDimitry Andric return ""; 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric BuiltinVaListKind getBuiltinVaListKind() const override { 1180b57cec5SDimitry Andric return TargetInfo::SystemZBuiltinVaList; 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric int getISARevision(StringRef Name) const; 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric bool isValidCPUName(StringRef Name) const override { 1240b57cec5SDimitry Andric return getISARevision(Name) != -1; 1250b57cec5SDimitry Andric } 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; 1280b57cec5SDimitry Andric 129753f127fSDimitry Andric bool isValidTuneCPUName(StringRef Name) const override { 130753f127fSDimitry Andric return isValidCPUName(Name); 131753f127fSDimitry Andric } 132753f127fSDimitry Andric 133753f127fSDimitry Andric void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override { 134753f127fSDimitry Andric fillValidCPUList(Values); 135753f127fSDimitry Andric } 136753f127fSDimitry Andric 1370b57cec5SDimitry Andric bool setCPU(const std::string &Name) override { 1380b57cec5SDimitry Andric CPU = Name; 1390b57cec5SDimitry Andric ISARevision = getISARevision(CPU); 1400b57cec5SDimitry Andric return ISARevision != -1; 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric bool 1440b57cec5SDimitry Andric initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, 1450b57cec5SDimitry Andric StringRef CPU, 1460b57cec5SDimitry Andric const std::vector<std::string> &FeaturesVec) const override { 1470b57cec5SDimitry Andric int ISARevision = getISARevision(CPU); 1480b57cec5SDimitry Andric if (ISARevision >= 10) 1490b57cec5SDimitry Andric Features["transactional-execution"] = true; 1500b57cec5SDimitry Andric if (ISARevision >= 11) 1510b57cec5SDimitry Andric Features["vector"] = true; 1520b57cec5SDimitry Andric if (ISARevision >= 12) 1530b57cec5SDimitry Andric Features["vector-enhancements-1"] = true; 1540b57cec5SDimitry Andric if (ISARevision >= 13) 1550b57cec5SDimitry Andric Features["vector-enhancements-2"] = true; 156fe6060f1SDimitry Andric if (ISARevision >= 14) 157fe6060f1SDimitry Andric Features["nnp-assist"] = true; 1580b57cec5SDimitry Andric return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric bool handleTargetFeatures(std::vector<std::string> &Features, 1620b57cec5SDimitry Andric DiagnosticsEngine &Diags) override { 1630b57cec5SDimitry Andric HasTransactionalExecution = false; 1640b57cec5SDimitry Andric HasVector = false; 1655ffd83dbSDimitry Andric SoftFloat = false; 1660b57cec5SDimitry Andric for (const auto &Feature : Features) { 1670b57cec5SDimitry Andric if (Feature == "+transactional-execution") 1680b57cec5SDimitry Andric HasTransactionalExecution = true; 1690b57cec5SDimitry Andric else if (Feature == "+vector") 1700b57cec5SDimitry Andric HasVector = true; 1715ffd83dbSDimitry Andric else if (Feature == "+soft-float") 1725ffd83dbSDimitry Andric SoftFloat = true; 1730b57cec5SDimitry Andric } 1745ffd83dbSDimitry Andric HasVector &= !SoftFloat; 1755ffd83dbSDimitry Andric 176bdd1243dSDimitry Andric // If we use the vector ABI, vector types are 64-bit aligned. The 177bdd1243dSDimitry Andric // DataLayout string is always set to this alignment as it is not a 178bdd1243dSDimitry Andric // requirement that it follows the alignment emitted by the front end. It 179bdd1243dSDimitry Andric // is assumed generally that the Datalayout should reflect only the 180bdd1243dSDimitry Andric // target triple and not any specific feature. 181bdd1243dSDimitry Andric if (HasVector && !getTriple().isOSzOS()) 1820b57cec5SDimitry Andric MaxVectorAlign = 64; 183bdd1243dSDimitry Andric 1840b57cec5SDimitry Andric return true; 1850b57cec5SDimitry Andric } 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric bool hasFeature(StringRef Feature) const override; 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { 1900b57cec5SDimitry Andric switch (CC) { 1910b57cec5SDimitry Andric case CC_C: 1920b57cec5SDimitry Andric case CC_Swift: 1930b57cec5SDimitry Andric case CC_OpenCLKernel: 1940b57cec5SDimitry Andric return CCCR_OK; 195fe6060f1SDimitry Andric case CC_SwiftAsync: 196fe6060f1SDimitry Andric return CCCR_Error; 1970b57cec5SDimitry Andric default: 1980b57cec5SDimitry Andric return CCCR_Warning; 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric StringRef getABI() const override { 2030b57cec5SDimitry Andric if (HasVector) 2040b57cec5SDimitry Andric return "vector"; 2050b57cec5SDimitry Andric return ""; 2060b57cec5SDimitry Andric } 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric const char *getLongDoubleMangling() const override { return "g"; } 2095ffd83dbSDimitry Andric 2100eae32dcSDimitry Andric bool hasBitIntType() const override { return true; } 211e8d8bef9SDimitry Andric 212e8d8bef9SDimitry Andric int getEHDataRegisterNumber(unsigned RegNo) const override { 213e8d8bef9SDimitry Andric return RegNo < 4 ? 6 + RegNo : -1; 214e8d8bef9SDimitry Andric } 2150b57cec5SDimitry Andric }; 2160b57cec5SDimitry Andric } // namespace targets 2170b57cec5SDimitry Andric } // namespace clang 2180b57cec5SDimitry Andric #endif // LLVM_CLANG_LIB_BASIC_TARGETS_SYSTEMZ_H 219