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