1e5dd7070Spatrick //===--- SystemZ.h - Declare SystemZ target feature support -----*- C++ -*-===// 2e5dd7070Spatrick // 3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information. 5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e5dd7070Spatrick // 7e5dd7070Spatrick //===----------------------------------------------------------------------===// 8e5dd7070Spatrick // 9e5dd7070Spatrick // This file declares SystemZ TargetInfo objects. 10e5dd7070Spatrick // 11e5dd7070Spatrick //===----------------------------------------------------------------------===// 12e5dd7070Spatrick 13e5dd7070Spatrick #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_SYSTEMZ_H 14e5dd7070Spatrick #define LLVM_CLANG_LIB_BASIC_TARGETS_SYSTEMZ_H 15e5dd7070Spatrick 16e5dd7070Spatrick #include "clang/Basic/TargetInfo.h" 17e5dd7070Spatrick #include "clang/Basic/TargetOptions.h" 18e5dd7070Spatrick #include "llvm/ADT/Triple.h" 19e5dd7070Spatrick #include "llvm/Support/Compiler.h" 20e5dd7070Spatrick 21e5dd7070Spatrick namespace clang { 22e5dd7070Spatrick namespace targets { 23e5dd7070Spatrick 24e5dd7070Spatrick class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo { 25e5dd7070Spatrick 26e5dd7070Spatrick static const char *const GCCRegNames[]; 27e5dd7070Spatrick std::string CPU; 28e5dd7070Spatrick int ISARevision; 29e5dd7070Spatrick bool HasTransactionalExecution; 30e5dd7070Spatrick bool HasVector; 31adae0cfdSpatrick bool SoftFloat; 32e5dd7070Spatrick 33e5dd7070Spatrick public: SystemZTargetInfo(const llvm::Triple & Triple,const TargetOptions &)34e5dd7070Spatrick SystemZTargetInfo(const llvm::Triple &Triple, const TargetOptions &) 35e5dd7070Spatrick : TargetInfo(Triple), CPU("z10"), ISARevision(8), 36adae0cfdSpatrick HasTransactionalExecution(false), HasVector(false), SoftFloat(false) { 37e5dd7070Spatrick IntMaxType = SignedLong; 38e5dd7070Spatrick Int64Type = SignedLong; 39e5dd7070Spatrick TLSSupported = true; 40e5dd7070Spatrick IntWidth = IntAlign = 32; 41e5dd7070Spatrick LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64; 42*7a9b00ceSrobert Int128Align = 64; 43e5dd7070Spatrick PointerWidth = PointerAlign = 64; 44e5dd7070Spatrick LongDoubleWidth = 128; 45e5dd7070Spatrick LongDoubleAlign = 64; 46e5dd7070Spatrick LongDoubleFormat = &llvm::APFloat::IEEEquad(); 47e5dd7070Spatrick DefaultAlignForAttributeAligned = 64; 48e5dd7070Spatrick MinGlobalAlign = 16; 49*7a9b00ceSrobert if (Triple.isOSzOS()) { 50*7a9b00ceSrobert // All vector types are default aligned on an 8-byte boundary, even if the 51*7a9b00ceSrobert // vector facility is not available. That is different from Linux. 52*7a9b00ceSrobert MaxVectorAlign = 64; 53*7a9b00ceSrobert // Compared to Linux/ELF, the data layout differs only in that name 54*7a9b00ceSrobert // mangling is GOFF. 55*7a9b00ceSrobert resetDataLayout( 56*7a9b00ceSrobert "E-m:l-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64"); 57*7a9b00ceSrobert } else 58*7a9b00ceSrobert resetDataLayout("E-m:e-i1:8:16-i8:8:16-i64:64-f128:64" 59*7a9b00ceSrobert "-v128:64-a:8:16-n32:64"); 60e5dd7070Spatrick MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; 61c090f204Sgkoehler HasStrictFP = true; 62e5dd7070Spatrick } 63e5dd7070Spatrick 64e5dd7070Spatrick void getTargetDefines(const LangOptions &Opts, 65e5dd7070Spatrick MacroBuilder &Builder) const override; 66e5dd7070Spatrick 67e5dd7070Spatrick ArrayRef<Builtin::Info> getTargetBuiltins() const override; 68e5dd7070Spatrick 69e5dd7070Spatrick ArrayRef<const char *> getGCCRegNames() const override; 70e5dd7070Spatrick getGCCRegAliases()71e5dd7070Spatrick ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { 72e5dd7070Spatrick // No aliases. 73*7a9b00ceSrobert return std::nullopt; 74e5dd7070Spatrick } 75e5dd7070Spatrick 76e5dd7070Spatrick ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override; 77e5dd7070Spatrick isSPRegName(StringRef RegName)78adae0cfdSpatrick bool isSPRegName(StringRef RegName) const override { 79adae0cfdSpatrick return RegName.equals("r15"); 80adae0cfdSpatrick } 81adae0cfdSpatrick 82e5dd7070Spatrick bool validateAsmConstraint(const char *&Name, 83e5dd7070Spatrick TargetInfo::ConstraintInfo &info) const override; 84e5dd7070Spatrick convertConstraint(const char * & Constraint)85*7a9b00ceSrobert std::string convertConstraint(const char *&Constraint) const override { 86*7a9b00ceSrobert switch (Constraint[0]) { 87*7a9b00ceSrobert case 'p': // Keep 'p' constraint. 88*7a9b00ceSrobert return std::string("p"); 89*7a9b00ceSrobert case 'Z': 90*7a9b00ceSrobert switch (Constraint[1]) { 91*7a9b00ceSrobert case 'Q': // Address with base and unsigned 12-bit displacement 92*7a9b00ceSrobert case 'R': // Likewise, plus an index 93*7a9b00ceSrobert case 'S': // Address with base and signed 20-bit displacement 94*7a9b00ceSrobert case 'T': // Likewise, plus an index 95*7a9b00ceSrobert // "^" hints llvm that this is a 2 letter constraint. 96*7a9b00ceSrobert // "Constraint++" is used to promote the string iterator 97*7a9b00ceSrobert // to the next constraint. 98*7a9b00ceSrobert return std::string("^") + std::string(Constraint++, 2); 99*7a9b00ceSrobert default: 100*7a9b00ceSrobert break; 101*7a9b00ceSrobert } 102*7a9b00ceSrobert break; 103*7a9b00ceSrobert default: 104*7a9b00ceSrobert break; 105*7a9b00ceSrobert } 106*7a9b00ceSrobert return TargetInfo::convertConstraint(Constraint); 107*7a9b00ceSrobert } 108*7a9b00ceSrobert getClobbers()109e5dd7070Spatrick const char *getClobbers() const override { 110e5dd7070Spatrick // FIXME: Is this really right? 111e5dd7070Spatrick return ""; 112e5dd7070Spatrick } 113e5dd7070Spatrick getBuiltinVaListKind()114e5dd7070Spatrick BuiltinVaListKind getBuiltinVaListKind() const override { 115e5dd7070Spatrick return TargetInfo::SystemZBuiltinVaList; 116e5dd7070Spatrick } 117e5dd7070Spatrick 118e5dd7070Spatrick int getISARevision(StringRef Name) const; 119e5dd7070Spatrick isValidCPUName(StringRef Name)120e5dd7070Spatrick bool isValidCPUName(StringRef Name) const override { 121e5dd7070Spatrick return getISARevision(Name) != -1; 122e5dd7070Spatrick } 123e5dd7070Spatrick 124e5dd7070Spatrick void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; 125e5dd7070Spatrick isValidTuneCPUName(StringRef Name)126*7a9b00ceSrobert bool isValidTuneCPUName(StringRef Name) const override { 127*7a9b00ceSrobert return isValidCPUName(Name); 128*7a9b00ceSrobert } 129*7a9b00ceSrobert fillValidTuneCPUList(SmallVectorImpl<StringRef> & Values)130*7a9b00ceSrobert void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override { 131*7a9b00ceSrobert fillValidCPUList(Values); 132*7a9b00ceSrobert } 133*7a9b00ceSrobert setCPU(const std::string & Name)134e5dd7070Spatrick bool setCPU(const std::string &Name) override { 135e5dd7070Spatrick CPU = Name; 136e5dd7070Spatrick ISARevision = getISARevision(CPU); 137e5dd7070Spatrick return ISARevision != -1; 138e5dd7070Spatrick } 139e5dd7070Spatrick 140e5dd7070Spatrick bool initFeatureMap(llvm::StringMap<bool> & Features,DiagnosticsEngine & Diags,StringRef CPU,const std::vector<std::string> & FeaturesVec)141e5dd7070Spatrick initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, 142e5dd7070Spatrick StringRef CPU, 143e5dd7070Spatrick const std::vector<std::string> &FeaturesVec) const override { 144e5dd7070Spatrick int ISARevision = getISARevision(CPU); 145e5dd7070Spatrick if (ISARevision >= 10) 146e5dd7070Spatrick Features["transactional-execution"] = true; 147e5dd7070Spatrick if (ISARevision >= 11) 148e5dd7070Spatrick Features["vector"] = true; 149e5dd7070Spatrick if (ISARevision >= 12) 150e5dd7070Spatrick Features["vector-enhancements-1"] = true; 151e5dd7070Spatrick if (ISARevision >= 13) 152e5dd7070Spatrick Features["vector-enhancements-2"] = true; 153a0747c9fSpatrick if (ISARevision >= 14) 154a0747c9fSpatrick Features["nnp-assist"] = true; 155e5dd7070Spatrick return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); 156e5dd7070Spatrick } 157e5dd7070Spatrick handleTargetFeatures(std::vector<std::string> & Features,DiagnosticsEngine & Diags)158e5dd7070Spatrick bool handleTargetFeatures(std::vector<std::string> &Features, 159e5dd7070Spatrick DiagnosticsEngine &Diags) override { 160e5dd7070Spatrick HasTransactionalExecution = false; 161e5dd7070Spatrick HasVector = false; 162adae0cfdSpatrick SoftFloat = false; 163e5dd7070Spatrick for (const auto &Feature : Features) { 164e5dd7070Spatrick if (Feature == "+transactional-execution") 165e5dd7070Spatrick HasTransactionalExecution = true; 166e5dd7070Spatrick else if (Feature == "+vector") 167e5dd7070Spatrick HasVector = true; 168adae0cfdSpatrick else if (Feature == "+soft-float") 169adae0cfdSpatrick SoftFloat = true; 170e5dd7070Spatrick } 171adae0cfdSpatrick HasVector &= !SoftFloat; 172adae0cfdSpatrick 173*7a9b00ceSrobert // If we use the vector ABI, vector types are 64-bit aligned. The 174*7a9b00ceSrobert // DataLayout string is always set to this alignment as it is not a 175*7a9b00ceSrobert // requirement that it follows the alignment emitted by the front end. It 176*7a9b00ceSrobert // is assumed generally that the Datalayout should reflect only the 177*7a9b00ceSrobert // target triple and not any specific feature. 178*7a9b00ceSrobert if (HasVector && !getTriple().isOSzOS()) 179e5dd7070Spatrick MaxVectorAlign = 64; 180*7a9b00ceSrobert 181e5dd7070Spatrick return true; 182e5dd7070Spatrick } 183e5dd7070Spatrick 184e5dd7070Spatrick bool hasFeature(StringRef Feature) const override; 185e5dd7070Spatrick checkCallingConvention(CallingConv CC)186e5dd7070Spatrick CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { 187e5dd7070Spatrick switch (CC) { 188e5dd7070Spatrick case CC_C: 189e5dd7070Spatrick case CC_Swift: 190e5dd7070Spatrick case CC_OpenCLKernel: 191e5dd7070Spatrick return CCCR_OK; 192a0747c9fSpatrick case CC_SwiftAsync: 193a0747c9fSpatrick return CCCR_Error; 194e5dd7070Spatrick default: 195e5dd7070Spatrick return CCCR_Warning; 196e5dd7070Spatrick } 197e5dd7070Spatrick } 198e5dd7070Spatrick getABI()199e5dd7070Spatrick StringRef getABI() const override { 200e5dd7070Spatrick if (HasVector) 201e5dd7070Spatrick return "vector"; 202e5dd7070Spatrick return ""; 203e5dd7070Spatrick } 204e5dd7070Spatrick getLongDoubleMangling()205e5dd7070Spatrick const char *getLongDoubleMangling() const override { return "g"; } 206adae0cfdSpatrick hasBitIntType()207*7a9b00ceSrobert bool hasBitIntType() const override { return true; } 208a0747c9fSpatrick getEHDataRegisterNumber(unsigned RegNo)209a0747c9fSpatrick int getEHDataRegisterNumber(unsigned RegNo) const override { 210a0747c9fSpatrick return RegNo < 4 ? 6 + RegNo : -1; 211a0747c9fSpatrick } 212e5dd7070Spatrick }; 213e5dd7070Spatrick } // namespace targets 214e5dd7070Spatrick } // namespace clang 215e5dd7070Spatrick #endif // LLVM_CLANG_LIB_BASIC_TARGETS_SYSTEMZ_H 216