1//===--- Sparc.h - declare sparc 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 Sparc TargetInfo objects.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_H
14#define LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_H
15#include "clang/Basic/TargetInfo.h"
16#include "clang/Basic/TargetOptions.h"
17#include "llvm/ADT/Triple.h"
18#include "llvm/Support/Compiler.h"
19namespace clang {
20namespace targets {
21// Shared base class for SPARC v8 (32-bit) and SPARC v9 (64-bit).
22class LLVM_LIBRARY_VISIBILITY SparcTargetInfo : public TargetInfo {
23  static const TargetInfo::GCCRegAlias GCCRegAliases[];
24  static const char *const GCCRegNames[];
25  bool SoftFloat;
26
27public:
28  SparcTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
29      : TargetInfo(Triple), SoftFloat(false) {}
30
31  int getEHDataRegisterNumber(unsigned RegNo) const override {
32    if (RegNo == 0)
33      return 24;
34    if (RegNo == 1)
35      return 25;
36    return -1;
37  }
38
39  bool handleTargetFeatures(std::vector<std::string> &Features,
40                            DiagnosticsEngine &Diags) override {
41    // Check if software floating point is enabled
42    auto Feature = llvm::find(Features, "+soft-float");
43    if (Feature != Features.end()) {
44      SoftFloat = true;
45    }
46    return true;
47  }
48  void getTargetDefines(const LangOptions &Opts,
49                        MacroBuilder &Builder) const override;
50
51  bool hasFeature(StringRef Feature) const override;
52
53  bool hasSjLjLowering() const override { return true; }
54
55  ArrayRef<Builtin::Info> getTargetBuiltins() const override {
56    // FIXME: Implement!
57    return None;
58  }
59  BuiltinVaListKind getBuiltinVaListKind() const override {
60    return TargetInfo::VoidPtrBuiltinVaList;
61  }
62  ArrayRef<const char *> getGCCRegNames() const override;
63  ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
64  bool validateAsmConstraint(const char *&Name,
65                             TargetInfo::ConstraintInfo &info) const override {
66    // FIXME: Implement!
67    switch (*Name) {
68    case 'I': // Signed 13-bit constant
69    case 'J': // Zero
70    case 'K': // 32-bit constant with the low 12 bits clear
71    case 'L': // A constant in the range supported by movcc (11-bit signed imm)
72    case 'M': // A constant in the range supported by movrcc (19-bit signed imm)
73    case 'N': // Same as 'K' but zext (required for SIMode)
74    case 'O': // The constant 4096
75      return true;
76
77    case 'f':
78    case 'e':
79      info.setAllowsRegister();
80      return true;
81    }
82    return false;
83  }
84  const char *getClobbers() const override {
85    // FIXME: Implement!
86    return "";
87  }
88
89  // No Sparc V7 for now, the backend doesn't support it anyway.
90  enum CPUKind {
91    CK_GENERIC,
92    CK_V8,
93    CK_SUPERSPARC,
94    CK_SPARCLITE,
95    CK_F934,
96    CK_HYPERSPARC,
97    CK_SPARCLITE86X,
98    CK_SPARCLET,
99    CK_TSC701,
100    CK_V9,
101    CK_ULTRASPARC,
102    CK_ULTRASPARC3,
103    CK_NIAGARA,
104    CK_NIAGARA2,
105    CK_NIAGARA3,
106    CK_NIAGARA4,
107    CK_MYRIAD2100,
108    CK_MYRIAD2150,
109    CK_MYRIAD2155,
110    CK_MYRIAD2450,
111    CK_MYRIAD2455,
112    CK_MYRIAD2x5x,
113    CK_MYRIAD2080,
114    CK_MYRIAD2085,
115    CK_MYRIAD2480,
116    CK_MYRIAD2485,
117    CK_MYRIAD2x8x,
118    CK_LEON2,
119    CK_LEON2_AT697E,
120    CK_LEON2_AT697F,
121    CK_LEON3,
122    CK_LEON3_UT699,
123    CK_LEON3_GR712RC,
124    CK_LEON4,
125    CK_LEON4_GR740
126  } CPU = CK_GENERIC;
127
128  enum CPUGeneration {
129    CG_V8,
130    CG_V9,
131  };
132
133  CPUGeneration getCPUGeneration(CPUKind Kind) const;
134
135  CPUKind getCPUKind(StringRef Name) const;
136
137  bool isValidCPUName(StringRef Name) const override {
138    return getCPUKind(Name) != CK_GENERIC;
139  }
140
141  void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
142
143  bool setCPU(const std::string &Name) override {
144    CPU = getCPUKind(Name);
145    return CPU != CK_GENERIC;
146  }
147};
148
149// SPARC v8 is the 32-bit mode selected by Triple::sparc.
150class LLVM_LIBRARY_VISIBILITY SparcV8TargetInfo : public SparcTargetInfo {
151public:
152  SparcV8TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
153      : SparcTargetInfo(Triple, Opts) {
154    resetDataLayout("E-m:e-p:32:32-i64:64-f128:64-n32-S64");
155    // NetBSD / OpenBSD use long (same as llvm default); everyone else uses int.
156    switch (getTriple().getOS()) {
157    default:
158      SizeType = UnsignedInt;
159      IntPtrType = SignedInt;
160      PtrDiffType = SignedInt;
161      break;
162    case llvm::Triple::NetBSD:
163    case llvm::Triple::OpenBSD:
164      SizeType = UnsignedLong;
165      IntPtrType = SignedLong;
166      PtrDiffType = SignedLong;
167      break;
168    }
169    // Up to 32 bits are lock-free atomic, but we're willing to do atomic ops
170    // on up to 64 bits.
171    MaxAtomicPromoteWidth = 64;
172    MaxAtomicInlineWidth = 32;
173  }
174
175  void getTargetDefines(const LangOptions &Opts,
176                        MacroBuilder &Builder) const override;
177
178  bool hasSjLjLowering() const override { return true; }
179};
180
181// SPARCV8el is the 32-bit little-endian mode selected by Triple::sparcel.
182class LLVM_LIBRARY_VISIBILITY SparcV8elTargetInfo : public SparcV8TargetInfo {
183public:
184  SparcV8elTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
185      : SparcV8TargetInfo(Triple, Opts) {
186    resetDataLayout("e-m:e-p:32:32-i64:64-f128:64-n32-S64");
187  }
188};
189
190// SPARC v9 is the 64-bit mode selected by Triple::sparcv9.
191class LLVM_LIBRARY_VISIBILITY SparcV9TargetInfo : public SparcTargetInfo {
192public:
193  SparcV9TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
194      : SparcTargetInfo(Triple, Opts) {
195    // FIXME: Support Sparc quad-precision long double?
196    resetDataLayout("E-m:e-i64:64-n32:64-S128");
197    // This is an LP64 platform.
198    LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
199
200    // OpenBSD uses long long for int64_t and intmax_t.
201    if (getTriple().isOSOpenBSD())
202      IntMaxType = SignedLongLong;
203    else
204      IntMaxType = SignedLong;
205    Int64Type = IntMaxType;
206
207    // The SPARCv8 System V ABI has long double 128-bits in size, but 64-bit
208    // aligned. The SPARCv9 SCD 2.4.1 says 16-byte aligned.
209    LongDoubleWidth = 128;
210    LongDoubleAlign = 128;
211    SuitableAlign = 128;
212    LongDoubleFormat = &llvm::APFloat::IEEEquad();
213    MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
214  }
215
216  void getTargetDefines(const LangOptions &Opts,
217                        MacroBuilder &Builder) const override;
218
219  bool isValidCPUName(StringRef Name) const override {
220    return getCPUGeneration(SparcTargetInfo::getCPUKind(Name)) == CG_V9;
221  }
222
223  void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
224
225  bool setCPU(const std::string &Name) override {
226    if (!SparcTargetInfo::setCPU(Name))
227      return false;
228    return getCPUGeneration(CPU) == CG_V9;
229  }
230};
231} // namespace targets
232} // namespace clang
233#endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPARC_H
234