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