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