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
33public:
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 = 128;
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