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