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