/src/llvm-project/clang/lib/Basic/Targets/PPC.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- PPC.h - Declare PPC 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 PPC TargetInfo objects. |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | |
13 | | #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_PPC_H |
14 | | #define LLVM_CLANG_LIB_BASIC_TARGETS_PPC_H |
15 | | |
16 | | #include "OSTargets.h" |
17 | | #include "clang/Basic/TargetInfo.h" |
18 | | #include "clang/Basic/TargetOptions.h" |
19 | | #include "llvm/ADT/StringSwitch.h" |
20 | | #include "llvm/Support/Compiler.h" |
21 | | #include "llvm/TargetParser/Triple.h" |
22 | | |
23 | | namespace clang { |
24 | | namespace targets { |
25 | | |
26 | | // PPC abstract base class |
27 | | class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo { |
28 | | |
29 | | /// Flags for architecture specific defines. |
30 | | typedef enum { |
31 | | ArchDefineNone = 0, |
32 | | ArchDefineName = 1 << 0, // <name> is substituted for arch name. |
33 | | ArchDefinePpcgr = 1 << 1, |
34 | | ArchDefinePpcsq = 1 << 2, |
35 | | ArchDefine440 = 1 << 3, |
36 | | ArchDefine603 = 1 << 4, |
37 | | ArchDefine604 = 1 << 5, |
38 | | ArchDefinePwr4 = 1 << 6, |
39 | | ArchDefinePwr5 = 1 << 7, |
40 | | ArchDefinePwr5x = 1 << 8, |
41 | | ArchDefinePwr6 = 1 << 9, |
42 | | ArchDefinePwr6x = 1 << 10, |
43 | | ArchDefinePwr7 = 1 << 11, |
44 | | ArchDefinePwr8 = 1 << 12, |
45 | | ArchDefinePwr9 = 1 << 13, |
46 | | ArchDefinePwr10 = 1 << 14, |
47 | | ArchDefineFuture = 1 << 15, |
48 | | ArchDefineA2 = 1 << 16, |
49 | | ArchDefineE500 = 1 << 18 |
50 | | } ArchDefineTypes; |
51 | | |
52 | | ArchDefineTypes ArchDefs = ArchDefineNone; |
53 | | static const char *const GCCRegNames[]; |
54 | | static const TargetInfo::GCCRegAlias GCCRegAliases[]; |
55 | | std::string CPU; |
56 | | enum PPCFloatABI { HardFloat, SoftFloat } FloatABI; |
57 | | |
58 | | // Target cpu features. |
59 | | bool HasAltivec = false; |
60 | | bool HasMMA = false; |
61 | | bool HasROPProtect = false; |
62 | | bool HasPrivileged = false; |
63 | | bool HasAIXSmallLocalExecTLS = false; |
64 | | bool HasVSX = false; |
65 | | bool UseCRBits = false; |
66 | | bool HasP8Vector = false; |
67 | | bool HasP8Crypto = false; |
68 | | bool HasDirectMove = false; |
69 | | bool HasHTM = false; |
70 | | bool HasBPERMD = false; |
71 | | bool HasExtDiv = false; |
72 | | bool HasP9Vector = false; |
73 | | bool HasSPE = false; |
74 | | bool PairedVectorMemops = false; |
75 | | bool HasP10Vector = false; |
76 | | bool HasPCRelativeMemops = false; |
77 | | bool HasPrefixInstrs = false; |
78 | | bool IsISA2_06 = false; |
79 | | bool IsISA2_07 = false; |
80 | | bool IsISA3_0 = false; |
81 | | bool IsISA3_1 = false; |
82 | | bool HasQuadwordAtomics = false; |
83 | | |
84 | | protected: |
85 | | std::string ABI; |
86 | | |
87 | | public: |
88 | | PPCTargetInfo(const llvm::Triple &Triple, const TargetOptions &) |
89 | 0 | : TargetInfo(Triple) { |
90 | 0 | SuitableAlign = 128; |
91 | 0 | LongDoubleWidth = LongDoubleAlign = 128; |
92 | 0 | LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble(); |
93 | 0 | HasStrictFP = true; |
94 | 0 | HasIbm128 = true; |
95 | 0 | } |
96 | | |
97 | | // Set the language option for altivec based on our value. |
98 | | void adjust(DiagnosticsEngine &Diags, LangOptions &Opts) override; |
99 | | |
100 | | // Note: GCC recognizes the following additional cpus: |
101 | | // 401, 403, 405, 405fp, 440fp, 464, 464fp, 476, 476fp, 505, 740, 801, |
102 | | // 821, 823, 8540, e300c2, e300c3, e500mc64, e6500, 860, cell, titan, rs64. |
103 | | bool isValidCPUName(StringRef Name) const override; |
104 | | void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; |
105 | | |
106 | 0 | bool setCPU(const std::string &Name) override { |
107 | 0 | bool CPUKnown = isValidCPUName(Name); |
108 | 0 | if (CPUKnown) { |
109 | 0 | CPU = Name; |
110 | | |
111 | | // CPU identification. |
112 | 0 | ArchDefs = |
113 | 0 | (ArchDefineTypes)llvm::StringSwitch<int>(CPU) |
114 | 0 | .Case("440", ArchDefineName) |
115 | 0 | .Case("450", ArchDefineName | ArchDefine440) |
116 | 0 | .Case("601", ArchDefineName) |
117 | 0 | .Case("602", ArchDefineName | ArchDefinePpcgr) |
118 | 0 | .Case("603", ArchDefineName | ArchDefinePpcgr) |
119 | 0 | .Case("603e", ArchDefineName | ArchDefine603 | ArchDefinePpcgr) |
120 | 0 | .Case("603ev", ArchDefineName | ArchDefine603 | ArchDefinePpcgr) |
121 | 0 | .Case("604", ArchDefineName | ArchDefinePpcgr) |
122 | 0 | .Case("604e", ArchDefineName | ArchDefine604 | ArchDefinePpcgr) |
123 | 0 | .Case("620", ArchDefineName | ArchDefinePpcgr) |
124 | 0 | .Case("630", ArchDefineName | ArchDefinePpcgr) |
125 | 0 | .Case("7400", ArchDefineName | ArchDefinePpcgr) |
126 | 0 | .Case("7450", ArchDefineName | ArchDefinePpcgr) |
127 | 0 | .Case("750", ArchDefineName | ArchDefinePpcgr) |
128 | 0 | .Case("970", ArchDefineName | ArchDefinePwr4 | ArchDefinePpcgr | |
129 | 0 | ArchDefinePpcsq) |
130 | 0 | .Case("a2", ArchDefineA2) |
131 | 0 | .Cases("power3", "pwr3", ArchDefinePpcgr) |
132 | 0 | .Cases("power4", "pwr4", |
133 | 0 | ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) |
134 | 0 | .Cases("power5", "pwr5", |
135 | 0 | ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr | |
136 | 0 | ArchDefinePpcsq) |
137 | 0 | .Cases("power5x", "pwr5x", |
138 | 0 | ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 | |
139 | 0 | ArchDefinePpcgr | ArchDefinePpcsq) |
140 | 0 | .Cases("power6", "pwr6", |
141 | 0 | ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 | |
142 | 0 | ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) |
143 | 0 | .Cases("power6x", "pwr6x", |
144 | 0 | ArchDefinePwr6x | ArchDefinePwr6 | ArchDefinePwr5x | |
145 | 0 | ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr | |
146 | 0 | ArchDefinePpcsq) |
147 | 0 | .Cases("power7", "pwr7", |
148 | 0 | ArchDefinePwr7 | ArchDefinePwr6 | ArchDefinePwr5x | |
149 | 0 | ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr | |
150 | 0 | ArchDefinePpcsq) |
151 | | // powerpc64le automatically defaults to at least power8. |
152 | 0 | .Cases("power8", "pwr8", "ppc64le", |
153 | 0 | ArchDefinePwr8 | ArchDefinePwr7 | ArchDefinePwr6 | |
154 | 0 | ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 | |
155 | 0 | ArchDefinePpcgr | ArchDefinePpcsq) |
156 | 0 | .Cases("power9", "pwr9", |
157 | 0 | ArchDefinePwr9 | ArchDefinePwr8 | ArchDefinePwr7 | |
158 | 0 | ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 | |
159 | 0 | ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq) |
160 | 0 | .Cases("power10", "pwr10", |
161 | 0 | ArchDefinePwr10 | ArchDefinePwr9 | ArchDefinePwr8 | |
162 | 0 | ArchDefinePwr7 | ArchDefinePwr6 | ArchDefinePwr5x | |
163 | 0 | ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr | |
164 | 0 | ArchDefinePpcsq) |
165 | 0 | .Case("future", |
166 | 0 | ArchDefineFuture | ArchDefinePwr10 | ArchDefinePwr9 | |
167 | 0 | ArchDefinePwr8 | ArchDefinePwr7 | ArchDefinePwr6 | |
168 | 0 | ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 | |
169 | 0 | ArchDefinePpcgr | ArchDefinePpcsq) |
170 | 0 | .Cases("8548", "e500", ArchDefineE500) |
171 | 0 | .Default(ArchDefineNone); |
172 | 0 | } |
173 | 0 | return CPUKnown; |
174 | 0 | } |
175 | | |
176 | 0 | StringRef getABI() const override { return ABI; } |
177 | | |
178 | | ArrayRef<Builtin::Info> getTargetBuiltins() const override; |
179 | | |
180 | 0 | bool isCLZForZeroUndef() const override { return false; } |
181 | | |
182 | | void getTargetDefines(const LangOptions &Opts, |
183 | | MacroBuilder &Builder) const override; |
184 | | |
185 | | bool |
186 | | initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, |
187 | | StringRef CPU, |
188 | | const std::vector<std::string> &FeaturesVec) const override; |
189 | | |
190 | | void addP10SpecificFeatures(llvm::StringMap<bool> &Features) const; |
191 | | void addFutureSpecificFeatures(llvm::StringMap<bool> &Features) const; |
192 | | |
193 | | bool handleTargetFeatures(std::vector<std::string> &Features, |
194 | | DiagnosticsEngine &Diags) override; |
195 | | |
196 | | bool hasFeature(StringRef Feature) const override; |
197 | | |
198 | | void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name, |
199 | | bool Enabled) const override; |
200 | | |
201 | 0 | bool supportsTargetAttributeTune() const override { return true; } |
202 | | |
203 | | ArrayRef<const char *> getGCCRegNames() const override; |
204 | | |
205 | | ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override; |
206 | | |
207 | | ArrayRef<TargetInfo::AddlRegName> getGCCAddlRegNames() const override; |
208 | | |
209 | | bool validateAsmConstraint(const char *&Name, |
210 | 0 | TargetInfo::ConstraintInfo &Info) const override { |
211 | 0 | switch (*Name) { |
212 | 0 | default: |
213 | 0 | return false; |
214 | 0 | case 'O': // Zero |
215 | 0 | break; |
216 | 0 | case 'f': // Floating point register |
217 | | // Don't use floating point registers on soft float ABI. |
218 | 0 | if (FloatABI == SoftFloat) |
219 | 0 | return false; |
220 | 0 | [[fallthrough]]; |
221 | 0 | case 'b': // Base register |
222 | 0 | Info.setAllowsRegister(); |
223 | 0 | break; |
224 | | // FIXME: The following are added to allow parsing. |
225 | | // I just took a guess at what the actions should be. |
226 | | // Also, is more specific checking needed? I.e. specific registers? |
227 | 0 | case 'd': // Floating point register (containing 64-bit value) |
228 | 0 | case 'v': // Altivec vector register |
229 | | // Don't use floating point and altivec vector registers |
230 | | // on soft float ABI |
231 | 0 | if (FloatABI == SoftFloat) |
232 | 0 | return false; |
233 | 0 | Info.setAllowsRegister(); |
234 | 0 | break; |
235 | 0 | case 'w': |
236 | 0 | switch (Name[1]) { |
237 | 0 | case 'd': // VSX vector register to hold vector double data |
238 | 0 | case 'f': // VSX vector register to hold vector float data |
239 | 0 | case 's': // VSX vector register to hold scalar double data |
240 | 0 | case 'w': // VSX vector register to hold scalar double data |
241 | 0 | case 'a': // Any VSX register |
242 | 0 | case 'c': // An individual CR bit |
243 | 0 | case 'i': // FP or VSX register to hold 64-bit integers data |
244 | 0 | break; |
245 | 0 | default: |
246 | 0 | return false; |
247 | 0 | } |
248 | 0 | Info.setAllowsRegister(); |
249 | 0 | Name++; // Skip over 'w'. |
250 | 0 | break; |
251 | 0 | case 'h': // `MQ', `CTR', or `LINK' register |
252 | 0 | case 'q': // `MQ' register |
253 | 0 | case 'c': // `CTR' register |
254 | 0 | case 'l': // `LINK' register |
255 | 0 | case 'x': // `CR' register (condition register) number 0 |
256 | 0 | case 'y': // `CR' register (condition register) |
257 | 0 | case 'z': // `XER[CA]' carry bit (part of the XER register) |
258 | 0 | Info.setAllowsRegister(); |
259 | 0 | break; |
260 | 0 | case 'I': // Signed 16-bit constant |
261 | 0 | case 'J': // Unsigned 16-bit constant shifted left 16 bits |
262 | | // (use `L' instead for SImode constants) |
263 | 0 | case 'K': // Unsigned 16-bit constant |
264 | 0 | case 'L': // Signed 16-bit constant shifted left 16 bits |
265 | 0 | case 'M': // Constant larger than 31 |
266 | 0 | case 'N': // Exact power of 2 |
267 | 0 | case 'P': // Constant whose negation is a signed 16-bit constant |
268 | 0 | case 'G': // Floating point constant that can be loaded into a |
269 | | // register with one instruction per word |
270 | 0 | case 'H': // Integer/Floating point constant that can be loaded |
271 | | // into a register using three instructions |
272 | 0 | break; |
273 | 0 | case 'm': // Memory operand. Note that on PowerPC targets, m can |
274 | | // include addresses that update the base register. It |
275 | | // is therefore only safe to use `m' in an asm statement |
276 | | // if that asm statement accesses the operand exactly once. |
277 | | // The asm statement must also use `%U<opno>' as a |
278 | | // placeholder for the "update" flag in the corresponding |
279 | | // load or store instruction. For example: |
280 | | // asm ("st%U0 %1,%0" : "=m" (mem) : "r" (val)); |
281 | | // is correct but: |
282 | | // asm ("st %1,%0" : "=m" (mem) : "r" (val)); |
283 | | // is not. Use es rather than m if you don't want the base |
284 | | // register to be updated. |
285 | 0 | case 'e': |
286 | 0 | if (Name[1] != 's') |
287 | 0 | return false; |
288 | | // es: A "stable" memory operand; that is, one which does not |
289 | | // include any automodification of the base register. Unlike |
290 | | // `m', this constraint can be used in asm statements that |
291 | | // might access the operand several times, or that might not |
292 | | // access it at all. |
293 | 0 | Info.setAllowsMemory(); |
294 | 0 | Name++; // Skip over 'e'. |
295 | 0 | break; |
296 | 0 | case 'Q': // Memory operand that is an offset from a register (it is |
297 | | // usually better to use `m' or `es' in asm statements) |
298 | 0 | Info.setAllowsRegister(); |
299 | 0 | [[fallthrough]]; |
300 | 0 | case 'Z': // Memory operand that is an indexed or indirect from a |
301 | | // register (it is usually better to use `m' or `es' in |
302 | | // asm statements) |
303 | 0 | Info.setAllowsMemory(); |
304 | 0 | break; |
305 | 0 | case 'R': // AIX TOC entry |
306 | 0 | case 'a': // Address operand that is an indexed or indirect from a |
307 | | // register (`p' is preferable for asm statements) |
308 | 0 | case 'S': // Constant suitable as a 64-bit mask operand |
309 | 0 | case 'T': // Constant suitable as a 32-bit mask operand |
310 | 0 | case 'U': // System V Release 4 small data area reference |
311 | 0 | case 't': // AND masks that can be performed by two rldic{l, r} |
312 | | // instructions |
313 | 0 | case 'W': // Vector constant that does not require memory |
314 | 0 | case 'j': // Vector constant that is all zeros. |
315 | 0 | break; |
316 | | // End FIXME. |
317 | 0 | } |
318 | 0 | return true; |
319 | 0 | } |
320 | | |
321 | 0 | std::string convertConstraint(const char *&Constraint) const override { |
322 | 0 | std::string R; |
323 | 0 | switch (*Constraint) { |
324 | 0 | case 'e': |
325 | 0 | case 'w': |
326 | | // Two-character constraint; add "^" hint for later parsing. |
327 | 0 | R = std::string("^") + std::string(Constraint, 2); |
328 | 0 | Constraint++; |
329 | 0 | break; |
330 | 0 | default: |
331 | 0 | return TargetInfo::convertConstraint(Constraint); |
332 | 0 | } |
333 | 0 | return R; |
334 | 0 | } |
335 | | |
336 | 0 | std::string_view getClobbers() const override { return ""; } |
337 | 0 | int getEHDataRegisterNumber(unsigned RegNo) const override { |
338 | 0 | if (RegNo == 0) |
339 | 0 | return 3; |
340 | 0 | if (RegNo == 1) |
341 | 0 | return 4; |
342 | 0 | return -1; |
343 | 0 | } |
344 | | |
345 | 0 | bool hasSjLjLowering() const override { return true; } |
346 | | |
347 | 0 | const char *getLongDoubleMangling() const override { |
348 | 0 | if (LongDoubleWidth == 64) |
349 | 0 | return "e"; |
350 | 0 | return LongDoubleFormat == &llvm::APFloat::PPCDoubleDouble() |
351 | 0 | ? "g" |
352 | 0 | : "u9__ieee128"; |
353 | 0 | } |
354 | 0 | const char *getFloat128Mangling() const override { return "u9__ieee128"; } |
355 | 0 | const char *getIbm128Mangling() const override { return "g"; } |
356 | | |
357 | 0 | bool hasBitIntType() const override { return true; } |
358 | | |
359 | 0 | bool isSPRegName(StringRef RegName) const override { |
360 | 0 | return RegName.equals("r1") || RegName.equals("x1"); |
361 | 0 | } |
362 | | }; |
363 | | |
364 | | class LLVM_LIBRARY_VISIBILITY PPC32TargetInfo : public PPCTargetInfo { |
365 | | public: |
366 | | PPC32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
367 | 0 | : PPCTargetInfo(Triple, Opts) { |
368 | 0 | if (Triple.isOSAIX()) |
369 | 0 | resetDataLayout("E-m:a-p:32:32-Fi32-i64:64-n32"); |
370 | 0 | else if (Triple.getArch() == llvm::Triple::ppcle) |
371 | 0 | resetDataLayout("e-m:e-p:32:32-Fn32-i64:64-n32"); |
372 | 0 | else |
373 | 0 | resetDataLayout("E-m:e-p:32:32-Fn32-i64:64-n32"); |
374 | |
|
375 | 0 | switch (getTriple().getOS()) { |
376 | 0 | case llvm::Triple::Linux: |
377 | 0 | case llvm::Triple::FreeBSD: |
378 | 0 | case llvm::Triple::NetBSD: |
379 | 0 | SizeType = UnsignedInt; |
380 | 0 | PtrDiffType = SignedInt; |
381 | 0 | IntPtrType = SignedInt; |
382 | 0 | break; |
383 | 0 | case llvm::Triple::AIX: |
384 | 0 | SizeType = UnsignedLong; |
385 | 0 | PtrDiffType = SignedLong; |
386 | 0 | IntPtrType = SignedLong; |
387 | 0 | LongDoubleWidth = 64; |
388 | 0 | LongDoubleAlign = DoubleAlign = 32; |
389 | 0 | LongDoubleFormat = &llvm::APFloat::IEEEdouble(); |
390 | 0 | break; |
391 | 0 | default: |
392 | 0 | break; |
393 | 0 | } |
394 | | |
395 | 0 | if (Triple.isOSFreeBSD() || Triple.isOSNetBSD() || Triple.isOSOpenBSD() || |
396 | 0 | Triple.isMusl()) { |
397 | 0 | LongDoubleWidth = LongDoubleAlign = 64; |
398 | 0 | LongDoubleFormat = &llvm::APFloat::IEEEdouble(); |
399 | 0 | } |
400 | | |
401 | | // PPC32 supports atomics up to 4 bytes. |
402 | 0 | MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32; |
403 | 0 | } |
404 | | |
405 | 0 | BuiltinVaListKind getBuiltinVaListKind() const override { |
406 | | // This is the ELF definition |
407 | 0 | return TargetInfo::PowerABIBuiltinVaList; |
408 | 0 | } |
409 | | }; |
410 | | |
411 | | // Note: ABI differences may eventually require us to have a separate |
412 | | // TargetInfo for little endian. |
413 | | class LLVM_LIBRARY_VISIBILITY PPC64TargetInfo : public PPCTargetInfo { |
414 | | public: |
415 | | PPC64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) |
416 | 0 | : PPCTargetInfo(Triple, Opts) { |
417 | 0 | LongWidth = LongAlign = PointerWidth = PointerAlign = 64; |
418 | 0 | IntMaxType = SignedLong; |
419 | 0 | Int64Type = SignedLong; |
420 | 0 | std::string DataLayout; |
421 | |
|
422 | 0 | if (Triple.isOSAIX()) { |
423 | | // TODO: Set appropriate ABI for AIX platform. |
424 | 0 | DataLayout = "E-m:a-Fi64-i64:64-n32:64"; |
425 | 0 | LongDoubleWidth = 64; |
426 | 0 | LongDoubleAlign = DoubleAlign = 32; |
427 | 0 | LongDoubleFormat = &llvm::APFloat::IEEEdouble(); |
428 | 0 | } else if ((Triple.getArch() == llvm::Triple::ppc64le)) { |
429 | 0 | DataLayout = "e-m:e-Fn32-i64:64-n32:64"; |
430 | 0 | ABI = "elfv2"; |
431 | 0 | } else { |
432 | 0 | DataLayout = "E-m:e"; |
433 | 0 | if (Triple.isPPC64ELFv2ABI()) { |
434 | 0 | ABI = "elfv2"; |
435 | 0 | DataLayout += "-Fn32"; |
436 | 0 | } else { |
437 | 0 | ABI = "elfv1"; |
438 | 0 | DataLayout += "-Fi64"; |
439 | 0 | } |
440 | 0 | DataLayout += "-i64:64-n32:64"; |
441 | 0 | } |
442 | |
|
443 | 0 | if (Triple.isOSFreeBSD() || Triple.isOSOpenBSD() || Triple.isMusl()) { |
444 | 0 | LongDoubleWidth = LongDoubleAlign = 64; |
445 | 0 | LongDoubleFormat = &llvm::APFloat::IEEEdouble(); |
446 | 0 | } |
447 | |
|
448 | 0 | if (Triple.isOSAIX() || Triple.isOSLinux()) |
449 | 0 | DataLayout += "-S128-v256:256:256-v512:512:512"; |
450 | 0 | resetDataLayout(DataLayout); |
451 | | |
452 | | // Newer PPC64 instruction sets support atomics up to 16 bytes. |
453 | 0 | MaxAtomicPromoteWidth = 128; |
454 | | // Baseline PPC64 supports inlining atomics up to 8 bytes. |
455 | 0 | MaxAtomicInlineWidth = 64; |
456 | 0 | } |
457 | | |
458 | 0 | void setMaxAtomicWidth() override { |
459 | | // For power8 and up, backend is able to inline 16-byte atomic lock free |
460 | | // code. |
461 | | // TODO: We should allow AIX to inline quadword atomics in the future. |
462 | 0 | if (!getTriple().isOSAIX() && hasFeature("quadword-atomics")) |
463 | 0 | MaxAtomicInlineWidth = 128; |
464 | 0 | } |
465 | | |
466 | 0 | BuiltinVaListKind getBuiltinVaListKind() const override { |
467 | 0 | return TargetInfo::CharPtrBuiltinVaList; |
468 | 0 | } |
469 | | |
470 | | // PPC64 Linux-specific ABI options. |
471 | 0 | bool setABI(const std::string &Name) override { |
472 | 0 | if (Name == "elfv1" || Name == "elfv2") { |
473 | 0 | ABI = Name; |
474 | 0 | return true; |
475 | 0 | } |
476 | 0 | return false; |
477 | 0 | } |
478 | | |
479 | 0 | CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { |
480 | 0 | switch (CC) { |
481 | 0 | case CC_Swift: |
482 | 0 | return CCCR_OK; |
483 | 0 | case CC_SwiftAsync: |
484 | 0 | return CCCR_Error; |
485 | 0 | default: |
486 | 0 | return CCCR_Warning; |
487 | 0 | } |
488 | 0 | } |
489 | | }; |
490 | | |
491 | | class LLVM_LIBRARY_VISIBILITY AIXPPC32TargetInfo : |
492 | | public AIXTargetInfo<PPC32TargetInfo> { |
493 | | public: |
494 | | using AIXTargetInfo::AIXTargetInfo; |
495 | 0 | BuiltinVaListKind getBuiltinVaListKind() const override { |
496 | 0 | return TargetInfo::CharPtrBuiltinVaList; |
497 | 0 | } |
498 | | }; |
499 | | |
500 | | class LLVM_LIBRARY_VISIBILITY AIXPPC64TargetInfo : |
501 | | public AIXTargetInfo<PPC64TargetInfo> { |
502 | | public: |
503 | | using AIXTargetInfo::AIXTargetInfo; |
504 | | }; |
505 | | |
506 | | } // namespace targets |
507 | | } // namespace clang |
508 | | #endif // LLVM_CLANG_LIB_BASIC_TARGETS_PPC_H |