| 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: | 
|---|
| 63 | SystemZTargetInfo(const llvm::Triple &Triple, const TargetOptions &) | 
|---|
| 64 | : TargetInfo(Triple), ISARevision(getISARevision(Name: "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(DL: "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(DL: "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 |  | 
|---|
| 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 |  | 
|---|
| 123 | ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { | 
|---|
| 124 | // No aliases. | 
|---|
| 125 | return {}; | 
|---|
| 126 | } | 
|---|
| 127 |  | 
|---|
| 128 | ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override; | 
|---|
| 129 |  | 
|---|
| 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 |  | 
|---|
| 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 |  | 
|---|
| 161 | std::string_view getClobbers() const override { | 
|---|
| 162 | // FIXME: Is this really right? | 
|---|
| 163 | return ""; | 
|---|
| 164 | } | 
|---|
| 165 |  | 
|---|
| 166 | BuiltinVaListKind getBuiltinVaListKind() const override { | 
|---|
| 167 | return TargetInfo::SystemZBuiltinVaList; | 
|---|
| 168 | } | 
|---|
| 169 |  | 
|---|
| 170 | int getISARevision(StringRef Name) const; | 
|---|
| 171 |  | 
|---|
| 172 | bool isValidCPUName(StringRef Name) const override { | 
|---|
| 173 | return getISARevision(Name) != -1; | 
|---|
| 174 | } | 
|---|
| 175 |  | 
|---|
| 176 | void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; | 
|---|
| 177 |  | 
|---|
| 178 | bool isValidTuneCPUName(StringRef Name) const override { | 
|---|
| 179 | return isValidCPUName(Name); | 
|---|
| 180 | } | 
|---|
| 181 |  | 
|---|
| 182 | void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override { | 
|---|
| 183 | fillValidCPUList(Values); | 
|---|
| 184 | } | 
|---|
| 185 |  | 
|---|
| 186 | bool setCPU(const std::string &Name) override { | 
|---|
| 187 | ISARevision = getISARevision(Name); | 
|---|
| 188 | return ISARevision != -1; | 
|---|
| 189 | } | 
|---|
| 190 |  | 
|---|
| 191 | bool | 
|---|
| 192 | initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, | 
|---|
| 193 | StringRef CPU, | 
|---|
| 194 | const std::vector<std::string> &FeaturesVec) const override { | 
|---|
| 195 | int ISARevision = getISARevision(Name: 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, FeatureVec: FeaturesVec); | 
|---|
| 211 | } | 
|---|
| 212 |  | 
|---|
| 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 |  | 
|---|
| 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 |  | 
|---|
| 257 | StringRef getABI() const override { | 
|---|
| 258 | if (HasVector) | 
|---|
| 259 | return "vector"; | 
|---|
| 260 | return ""; | 
|---|
| 261 | } | 
|---|
| 262 |  | 
|---|
| 263 | const char *getLongDoubleMangling() const override { return "g"; } | 
|---|
| 264 |  | 
|---|
| 265 | bool hasBitIntType() const override { return true; } | 
|---|
| 266 |  | 
|---|
| 267 | int getEHDataRegisterNumber(unsigned RegNo) const override { | 
|---|
| 268 | return RegNo < 4 ? 6 + RegNo : -1; | 
|---|
| 269 | } | 
|---|
| 270 |  | 
|---|
| 271 | bool hasSjLjLowering() const override { return true; } | 
|---|
| 272 |  | 
|---|
| 273 | std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override { | 
|---|
| 274 | return std::make_pair(x: 256, y: 256); | 
|---|
| 275 | } | 
|---|
| 276 | uint64_t getPointerWidthV(LangAS AddrSpace) const override { | 
|---|
| 277 | return (getTriple().isOSzOS() && getTriple().isArch64Bit() && | 
|---|
| 278 | getTargetAddressSpace(AS: AddrSpace) == ptr32) | 
|---|
| 279 | ? 32 | 
|---|
| 280 | : PointerWidth; | 
|---|
| 281 | } | 
|---|
| 282 |  | 
|---|
| 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 |  | 
|---|