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" 1906c3fb27SDimitry 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; 32*0fca6ea1SDimitry Andric bool UnalignedSymbols; 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric public: 350b57cec5SDimitry Andric SystemZTargetInfo(const llvm::Triple &Triple, const TargetOptions &) 360b57cec5SDimitry Andric : TargetInfo(Triple), CPU("z10"), ISARevision(8), 37*0fca6ea1SDimitry Andric HasTransactionalExecution(false), HasVector(false), SoftFloat(false), 38*0fca6ea1SDimitry Andric UnalignedSymbols(false) { 390b57cec5SDimitry Andric IntMaxType = SignedLong; 400b57cec5SDimitry Andric Int64Type = SignedLong; 410b57cec5SDimitry Andric IntWidth = IntAlign = 32; 420b57cec5SDimitry Andric LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64; 43bdd1243dSDimitry Andric Int128Align = 64; 440b57cec5SDimitry Andric PointerWidth = PointerAlign = 64; 450b57cec5SDimitry Andric LongDoubleWidth = 128; 460b57cec5SDimitry Andric LongDoubleAlign = 64; 470b57cec5SDimitry Andric LongDoubleFormat = &llvm::APFloat::IEEEquad(); 480b57cec5SDimitry Andric DefaultAlignForAttributeAligned = 64; 490b57cec5SDimitry Andric MinGlobalAlign = 16; 50*0fca6ea1SDimitry Andric HasUnalignedAccess = true; 51349cc55cSDimitry Andric if (Triple.isOSzOS()) { 5206c3fb27SDimitry Andric TLSSupported = false; 53349cc55cSDimitry Andric // All vector types are default aligned on an 8-byte boundary, even if the 54349cc55cSDimitry Andric // vector facility is not available. That is different from Linux. 55349cc55cSDimitry Andric MaxVectorAlign = 64; 5606c3fb27SDimitry Andric // Compared to Linux/ELF, the data layout differs only in some details: 5706c3fb27SDimitry Andric // - name mangling is GOFF. 5806c3fb27SDimitry Andric // - 32 bit pointers, either as default or special address space 5906c3fb27SDimitry Andric resetDataLayout("E-m:l-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-" 6006c3fb27SDimitry Andric "a:8:16-n32:64"); 6106c3fb27SDimitry Andric } else { 6206c3fb27SDimitry Andric TLSSupported = true; 63bdd1243dSDimitry Andric resetDataLayout("E-m:e-i1:8:16-i8:8:16-i64:64-f128:64" 64bdd1243dSDimitry Andric "-v128:64-a:8:16-n32:64"); 6506c3fb27SDimitry Andric } 665f757f3fSDimitry Andric MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 128; 675ffd83dbSDimitry Andric HasStrictFP = true; 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric 70*0fca6ea1SDimitry Andric unsigned getMinGlobalAlign(uint64_t Size, bool HasNonWeakDef) const override; 71*0fca6ea1SDimitry Andric 720b57cec5SDimitry Andric void getTargetDefines(const LangOptions &Opts, 730b57cec5SDimitry Andric MacroBuilder &Builder) const override; 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric ArrayRef<Builtin::Info> getTargetBuiltins() const override; 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric ArrayRef<const char *> getGCCRegNames() const override; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { 800b57cec5SDimitry Andric // No aliases. 81bdd1243dSDimitry Andric return std::nullopt; 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override; 850b57cec5SDimitry Andric 865ffd83dbSDimitry Andric bool isSPRegName(StringRef RegName) const override { 87*0fca6ea1SDimitry Andric return RegName == "r15"; 885ffd83dbSDimitry Andric } 895ffd83dbSDimitry Andric 900b57cec5SDimitry Andric bool validateAsmConstraint(const char *&Name, 910b57cec5SDimitry Andric TargetInfo::ConstraintInfo &info) const override; 920b57cec5SDimitry Andric 9381ad6265SDimitry Andric std::string convertConstraint(const char *&Constraint) const override { 9481ad6265SDimitry Andric switch (Constraint[0]) { 9581ad6265SDimitry Andric case 'p': // Keep 'p' constraint. 9681ad6265SDimitry Andric return std::string("p"); 9781ad6265SDimitry Andric case 'Z': 9881ad6265SDimitry Andric switch (Constraint[1]) { 9981ad6265SDimitry Andric case 'Q': // Address with base and unsigned 12-bit displacement 10081ad6265SDimitry Andric case 'R': // Likewise, plus an index 10181ad6265SDimitry Andric case 'S': // Address with base and signed 20-bit displacement 10281ad6265SDimitry Andric case 'T': // Likewise, plus an index 10381ad6265SDimitry Andric // "^" hints llvm that this is a 2 letter constraint. 10481ad6265SDimitry Andric // "Constraint++" is used to promote the string iterator 10581ad6265SDimitry Andric // to the next constraint. 10681ad6265SDimitry Andric return std::string("^") + std::string(Constraint++, 2); 10781ad6265SDimitry Andric default: 10881ad6265SDimitry Andric break; 10981ad6265SDimitry Andric } 11081ad6265SDimitry Andric break; 11181ad6265SDimitry Andric default: 11281ad6265SDimitry Andric break; 11381ad6265SDimitry Andric } 11481ad6265SDimitry Andric return TargetInfo::convertConstraint(Constraint); 11581ad6265SDimitry Andric } 11681ad6265SDimitry Andric 11706c3fb27SDimitry Andric std::string_view getClobbers() const override { 1180b57cec5SDimitry Andric // FIXME: Is this really right? 1190b57cec5SDimitry Andric return ""; 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric BuiltinVaListKind getBuiltinVaListKind() const override { 1230b57cec5SDimitry Andric return TargetInfo::SystemZBuiltinVaList; 1240b57cec5SDimitry Andric } 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric int getISARevision(StringRef Name) const; 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric bool isValidCPUName(StringRef Name) const override { 1290b57cec5SDimitry Andric return getISARevision(Name) != -1; 1300b57cec5SDimitry Andric } 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; 1330b57cec5SDimitry Andric 134753f127fSDimitry Andric bool isValidTuneCPUName(StringRef Name) const override { 135753f127fSDimitry Andric return isValidCPUName(Name); 136753f127fSDimitry Andric } 137753f127fSDimitry Andric 138753f127fSDimitry Andric void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override { 139753f127fSDimitry Andric fillValidCPUList(Values); 140753f127fSDimitry Andric } 141753f127fSDimitry Andric 1420b57cec5SDimitry Andric bool setCPU(const std::string &Name) override { 1430b57cec5SDimitry Andric CPU = Name; 1440b57cec5SDimitry Andric ISARevision = getISARevision(CPU); 1450b57cec5SDimitry Andric return ISARevision != -1; 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric bool 1490b57cec5SDimitry Andric initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, 1500b57cec5SDimitry Andric StringRef CPU, 1510b57cec5SDimitry Andric const std::vector<std::string> &FeaturesVec) const override { 1520b57cec5SDimitry Andric int ISARevision = getISARevision(CPU); 1530b57cec5SDimitry Andric if (ISARevision >= 10) 1540b57cec5SDimitry Andric Features["transactional-execution"] = true; 1550b57cec5SDimitry Andric if (ISARevision >= 11) 1560b57cec5SDimitry Andric Features["vector"] = true; 1570b57cec5SDimitry Andric if (ISARevision >= 12) 1580b57cec5SDimitry Andric Features["vector-enhancements-1"] = true; 1590b57cec5SDimitry Andric if (ISARevision >= 13) 1600b57cec5SDimitry Andric Features["vector-enhancements-2"] = true; 161fe6060f1SDimitry Andric if (ISARevision >= 14) 162fe6060f1SDimitry Andric Features["nnp-assist"] = true; 1630b57cec5SDimitry Andric return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric bool handleTargetFeatures(std::vector<std::string> &Features, 1670b57cec5SDimitry Andric DiagnosticsEngine &Diags) override { 1680b57cec5SDimitry Andric HasTransactionalExecution = false; 1690b57cec5SDimitry Andric HasVector = false; 1705ffd83dbSDimitry Andric SoftFloat = false; 171*0fca6ea1SDimitry Andric UnalignedSymbols = false; 1720b57cec5SDimitry Andric for (const auto &Feature : Features) { 1730b57cec5SDimitry Andric if (Feature == "+transactional-execution") 1740b57cec5SDimitry Andric HasTransactionalExecution = true; 1750b57cec5SDimitry Andric else if (Feature == "+vector") 1760b57cec5SDimitry Andric HasVector = true; 1775ffd83dbSDimitry Andric else if (Feature == "+soft-float") 1785ffd83dbSDimitry Andric SoftFloat = true; 179*0fca6ea1SDimitry Andric else if (Feature == "+unaligned-symbols") 180*0fca6ea1SDimitry Andric UnalignedSymbols = true; 1810b57cec5SDimitry Andric } 1825ffd83dbSDimitry Andric HasVector &= !SoftFloat; 1835ffd83dbSDimitry Andric 184bdd1243dSDimitry Andric // If we use the vector ABI, vector types are 64-bit aligned. The 185bdd1243dSDimitry Andric // DataLayout string is always set to this alignment as it is not a 186bdd1243dSDimitry Andric // requirement that it follows the alignment emitted by the front end. It 187bdd1243dSDimitry Andric // is assumed generally that the Datalayout should reflect only the 188bdd1243dSDimitry Andric // target triple and not any specific feature. 189bdd1243dSDimitry Andric if (HasVector && !getTriple().isOSzOS()) 1900b57cec5SDimitry Andric MaxVectorAlign = 64; 191bdd1243dSDimitry Andric 1920b57cec5SDimitry Andric return true; 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric bool hasFeature(StringRef Feature) const override; 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { 1980b57cec5SDimitry Andric switch (CC) { 1990b57cec5SDimitry Andric case CC_C: 2000b57cec5SDimitry Andric case CC_Swift: 2010b57cec5SDimitry Andric case CC_OpenCLKernel: 2020b57cec5SDimitry Andric return CCCR_OK; 203fe6060f1SDimitry Andric case CC_SwiftAsync: 204fe6060f1SDimitry Andric return CCCR_Error; 2050b57cec5SDimitry Andric default: 2060b57cec5SDimitry Andric return CCCR_Warning; 2070b57cec5SDimitry Andric } 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric StringRef getABI() const override { 2110b57cec5SDimitry Andric if (HasVector) 2120b57cec5SDimitry Andric return "vector"; 2130b57cec5SDimitry Andric return ""; 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric const char *getLongDoubleMangling() const override { return "g"; } 2175ffd83dbSDimitry Andric 2180eae32dcSDimitry Andric bool hasBitIntType() const override { return true; } 219e8d8bef9SDimitry Andric 220e8d8bef9SDimitry Andric int getEHDataRegisterNumber(unsigned RegNo) const override { 221e8d8bef9SDimitry Andric return RegNo < 4 ? 6 + RegNo : -1; 222e8d8bef9SDimitry Andric } 223*0fca6ea1SDimitry Andric 224*0fca6ea1SDimitry Andric std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override { 225*0fca6ea1SDimitry Andric return std::make_pair(256, 256); 226*0fca6ea1SDimitry Andric } 2270b57cec5SDimitry Andric }; 2280b57cec5SDimitry Andric } // namespace targets 2290b57cec5SDimitry Andric } // namespace clang 2300b57cec5SDimitry Andric #endif // LLVM_CLANG_LIB_BASIC_TARGETS_SYSTEMZ_H 231