xref: /freebsd/contrib/llvm-project/clang/lib/Basic/Targets/SystemZ.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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