1 //===--- SystemZ.h - Declare SystemZ target feature support -----*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file declares SystemZ TargetInfo objects. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_SYSTEMZ_H 14 #define LLVM_CLANG_LIB_BASIC_TARGETS_SYSTEMZ_H 15 16 #include "clang/Basic/TargetInfo.h" 17 #include "clang/Basic/TargetOptions.h" 18 #include "llvm/Support/Compiler.h" 19 #include "llvm/TargetParser/Triple.h" 20 21 namespace clang { 22 namespace targets { 23 24 static const unsigned ZOSAddressMap[] = { 25 0, // Default 26 0, // opencl_global 27 0, // opencl_local 28 0, // opencl_constant 29 0, // opencl_private 30 0, // opencl_generic 31 0, // opencl_global_device 32 0, // opencl_global_host 33 0, // cuda_device 34 0, // cuda_constant 35 0, // cuda_shared 36 0, // sycl_global 37 0, // sycl_global_device 38 0, // sycl_global_host 39 0, // sycl_local 40 0, // sycl_private 41 0, // ptr32_sptr 42 1, // ptr32_uptr 43 0, // ptr64 44 0, // hlsl_groupshared 45 0, // hlsl_constant 46 0, // hlsl_private 47 0, // hlsl_device 48 0, // hlsl_input 49 0 // wasm_funcref 50 }; 51 52 class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo { 53 54 static const char *const GCCRegNames[]; 55 int ISARevision; 56 bool HasTransactionalExecution; 57 bool HasVector; 58 bool SoftFloat; 59 bool UnalignedSymbols; 60 enum AddrSpace { ptr32 = 1 }; 61 62 public: SystemZTargetInfo(const llvm::Triple & Triple,const TargetOptions &)63 SystemZTargetInfo(const llvm::Triple &Triple, const TargetOptions &) 64 : TargetInfo(Triple), ISARevision(getISARevision("z10")), 65 HasTransactionalExecution(false), HasVector(false), SoftFloat(false), 66 UnalignedSymbols(false) { 67 IntMaxType = SignedLong; 68 Int64Type = SignedLong; 69 IntWidth = IntAlign = 32; 70 LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64; 71 Int128Align = 64; 72 PointerWidth = PointerAlign = 64; 73 LongDoubleWidth = 128; 74 LongDoubleAlign = 64; 75 LongDoubleFormat = &llvm::APFloat::IEEEquad(); 76 DefaultAlignForAttributeAligned = 64; 77 MinGlobalAlign = 16; 78 HasUnalignedAccess = true; 79 if (Triple.isOSzOS()) { 80 if (Triple.isArch64Bit()) { 81 AddrSpaceMap = &ZOSAddressMap; 82 } 83 TLSSupported = false; 84 // All vector types are default aligned on an 8-byte boundary, even if the 85 // vector facility is not available. That is different from Linux. 86 MaxVectorAlign = 64; 87 // Compared to Linux/ELF, the data layout differs only in some details: 88 // - name mangling is GOFF. 89 // - 32 bit pointers, either as default or special address space 90 resetDataLayout("E-m:l-p1:32:32-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-" 91 "a:8:16-n32:64"); 92 } else { 93 // Support _Float16. 94 HasFloat16 = true; 95 TLSSupported = true; 96 resetDataLayout("E-m:e-i1:8:16-i8:8:16-i64:64-f128:64" 97 "-v128:64-a:8:16-n32:64"); 98 } 99 MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 128; 100 101 // True if the backend supports operations on the half LLVM IR type. 102 // By setting this to false, conversions will happen for _Float16 around 103 // a statement by default, with operations done in float. However, if 104 // -ffloat16-excess-precision=none is given, no conversions will be made 105 // and instead the backend will promote each half operation to float 106 // individually. 107 HasLegalHalfType = false; 108 109 HasStrictFP = true; 110 } 111 112 unsigned getMinGlobalAlign(uint64_t Size, bool HasNonWeakDef) const override; 113 useFP16ConversionIntrinsics()114 bool useFP16ConversionIntrinsics() const override { return false; } 115 116 void getTargetDefines(const LangOptions &Opts, 117 MacroBuilder &Builder) const override; 118 119 llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override; 120 121 ArrayRef<const char *> getGCCRegNames() const override; 122 getGCCRegAliases()123 ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { 124 // No aliases. 125 return {}; 126 } 127 128 ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override; 129 isSPRegName(StringRef RegName)130 bool isSPRegName(StringRef RegName) const override { 131 return RegName == "r15"; 132 } 133 134 bool validateAsmConstraint(const char *&Name, 135 TargetInfo::ConstraintInfo &info) const override; 136 convertConstraint(const char * & Constraint)137 std::string convertConstraint(const char *&Constraint) const override { 138 switch (Constraint[0]) { 139 case 'p': // Keep 'p' constraint. 140 return std::string("p"); 141 case 'Z': 142 switch (Constraint[1]) { 143 case 'Q': // Address with base and unsigned 12-bit displacement 144 case 'R': // Likewise, plus an index 145 case 'S': // Address with base and signed 20-bit displacement 146 case 'T': // Likewise, plus an index 147 // "^" hints llvm that this is a 2 letter constraint. 148 // "Constraint++" is used to promote the string iterator 149 // to the next constraint. 150 return std::string("^") + std::string(Constraint++, 2); 151 default: 152 break; 153 } 154 break; 155 default: 156 break; 157 } 158 return TargetInfo::convertConstraint(Constraint); 159 } 160 getClobbers()161 std::string_view getClobbers() const override { 162 // FIXME: Is this really right? 163 return ""; 164 } 165 getBuiltinVaListKind()166 BuiltinVaListKind getBuiltinVaListKind() const override { 167 return TargetInfo::SystemZBuiltinVaList; 168 } 169 170 int getISARevision(StringRef Name) const; 171 isValidCPUName(StringRef Name)172 bool isValidCPUName(StringRef Name) const override { 173 return getISARevision(Name) != -1; 174 } 175 176 void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; 177 isValidTuneCPUName(StringRef Name)178 bool isValidTuneCPUName(StringRef Name) const override { 179 return isValidCPUName(Name); 180 } 181 fillValidTuneCPUList(SmallVectorImpl<StringRef> & Values)182 void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override { 183 fillValidCPUList(Values); 184 } 185 setCPU(const std::string & Name)186 bool setCPU(const std::string &Name) override { 187 ISARevision = getISARevision(Name); 188 return ISARevision != -1; 189 } 190 191 bool initFeatureMap(llvm::StringMap<bool> & Features,DiagnosticsEngine & Diags,StringRef CPU,const std::vector<std::string> & FeaturesVec)192 initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, 193 StringRef CPU, 194 const std::vector<std::string> &FeaturesVec) const override { 195 int ISARevision = getISARevision(CPU); 196 if (ISARevision >= 10) 197 Features["transactional-execution"] = true; 198 if (ISARevision >= 11) 199 Features["vector"] = true; 200 if (ISARevision >= 12) 201 Features["vector-enhancements-1"] = true; 202 if (ISARevision >= 13) 203 Features["vector-enhancements-2"] = true; 204 if (ISARevision >= 14) 205 Features["nnp-assist"] = true; 206 if (ISARevision >= 15) { 207 Features["miscellaneous-extensions-4"] = true; 208 Features["vector-enhancements-3"] = true; 209 } 210 return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); 211 } 212 handleTargetFeatures(std::vector<std::string> & Features,DiagnosticsEngine & Diags)213 bool handleTargetFeatures(std::vector<std::string> &Features, 214 DiagnosticsEngine &Diags) override { 215 HasTransactionalExecution = false; 216 HasVector = false; 217 SoftFloat = false; 218 UnalignedSymbols = false; 219 for (const auto &Feature : Features) { 220 if (Feature == "+transactional-execution") 221 HasTransactionalExecution = true; 222 else if (Feature == "+vector") 223 HasVector = true; 224 else if (Feature == "+soft-float") 225 SoftFloat = true; 226 else if (Feature == "+unaligned-symbols") 227 UnalignedSymbols = true; 228 } 229 HasVector &= !SoftFloat; 230 231 // If we use the vector ABI, vector types are 64-bit aligned. The 232 // DataLayout string is always set to this alignment as it is not a 233 // requirement that it follows the alignment emitted by the front end. It 234 // is assumed generally that the Datalayout should reflect only the 235 // target triple and not any specific feature. 236 if (HasVector && !getTriple().isOSzOS()) 237 MaxVectorAlign = 64; 238 239 return true; 240 } 241 242 bool hasFeature(StringRef Feature) const override; 243 checkCallingConvention(CallingConv CC)244 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { 245 switch (CC) { 246 case CC_C: 247 case CC_Swift: 248 case CC_DeviceKernel: 249 return CCCR_OK; 250 case CC_SwiftAsync: 251 return CCCR_Error; 252 default: 253 return CCCR_Warning; 254 } 255 } 256 getABI()257 StringRef getABI() const override { 258 if (HasVector) 259 return "vector"; 260 return ""; 261 } 262 getLongDoubleMangling()263 const char *getLongDoubleMangling() const override { return "g"; } 264 hasBitIntType()265 bool hasBitIntType() const override { return true; } 266 getEHDataRegisterNumber(unsigned RegNo)267 int getEHDataRegisterNumber(unsigned RegNo) const override { 268 return RegNo < 4 ? 6 + RegNo : -1; 269 } 270 hasSjLjLowering()271 bool hasSjLjLowering() const override { return true; } 272 hardwareInterferenceSizes()273 std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override { 274 return std::make_pair(256, 256); 275 } getPointerWidthV(LangAS AddrSpace)276 uint64_t getPointerWidthV(LangAS AddrSpace) const override { 277 return (getTriple().isOSzOS() && getTriple().isArch64Bit() && 278 getTargetAddressSpace(AddrSpace) == ptr32) 279 ? 32 280 : PointerWidth; 281 } 282 getPointerAlignV(LangAS AddrSpace)283 uint64_t getPointerAlignV(LangAS AddrSpace) const override { 284 return getPointerWidthV(AddrSpace); 285 } 286 }; 287 } // namespace targets 288 } // namespace clang 289 #endif // LLVM_CLANG_LIB_BASIC_TARGETS_SYSTEMZ_H 290