/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Basic/TargetInfo.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- TargetInfo.cpp - Information about Target machine ----------------===// |
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 implements the TargetInfo interface. |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | |
13 | | #include "clang/Basic/TargetInfo.h" |
14 | | #include "clang/Basic/AddressSpaces.h" |
15 | | #include "clang/Basic/CharInfo.h" |
16 | | #include "clang/Basic/Diagnostic.h" |
17 | | #include "clang/Basic/DiagnosticFrontend.h" |
18 | | #include "clang/Basic/LangOptions.h" |
19 | | #include "llvm/ADT/APFloat.h" |
20 | | #include "llvm/ADT/STLExtras.h" |
21 | | #include "llvm/Support/ErrorHandling.h" |
22 | | #include "llvm/TargetParser/TargetParser.h" |
23 | | #include <cstdlib> |
24 | | using namespace clang; |
25 | | |
26 | | static const LangASMap DefaultAddrSpaceMap = {0}; |
27 | | // The fake address space map must have a distinct entry for each |
28 | | // language-specific address space. |
29 | | static const LangASMap FakeAddrSpaceMap = { |
30 | | 0, // Default |
31 | | 1, // opencl_global |
32 | | 3, // opencl_local |
33 | | 2, // opencl_constant |
34 | | 0, // opencl_private |
35 | | 4, // opencl_generic |
36 | | 5, // opencl_global_device |
37 | | 6, // opencl_global_host |
38 | | 7, // cuda_device |
39 | | 8, // cuda_constant |
40 | | 9, // cuda_shared |
41 | | 1, // sycl_global |
42 | | 5, // sycl_global_device |
43 | | 6, // sycl_global_host |
44 | | 3, // sycl_local |
45 | | 0, // sycl_private |
46 | | 10, // ptr32_sptr |
47 | | 11, // ptr32_uptr |
48 | | 12, // ptr64 |
49 | | 13, // hlsl_groupshared |
50 | | 20, // wasm_funcref |
51 | | }; |
52 | | |
53 | | // TargetInfo Constructor. |
54 | 101k | TargetInfo::TargetInfo(const llvm::Triple &T) : Triple(T) { |
55 | | // Set defaults. Defaults are set for a 32-bit RISC platform, like PPC or |
56 | | // SPARC. These should be overridden by concrete targets as needed. |
57 | 101k | BigEndian = !T.isLittleEndian(); |
58 | 101k | TLSSupported = true; |
59 | 101k | VLASupported = true; |
60 | 101k | NoAsmVariants = false; |
61 | 101k | HasLegalHalfType = false; |
62 | 101k | HalfArgsAndReturns = false; |
63 | 101k | HasFloat128 = false; |
64 | 101k | HasIbm128 = false; |
65 | 101k | HasFloat16 = false; |
66 | 101k | HasBFloat16 = false; |
67 | 101k | HasFullBFloat16 = false; |
68 | 101k | HasLongDouble = true; |
69 | 101k | HasFPReturn = true; |
70 | 101k | HasStrictFP = false; |
71 | 101k | PointerWidth = PointerAlign = 32; |
72 | 101k | BoolWidth = BoolAlign = 8; |
73 | 101k | IntWidth = IntAlign = 32; |
74 | 101k | LongWidth = LongAlign = 32; |
75 | 101k | LongLongWidth = LongLongAlign = 64; |
76 | 101k | Int128Align = 128; |
77 | | |
78 | | // Fixed point default bit widths |
79 | 101k | ShortAccumWidth = ShortAccumAlign = 16; |
80 | 101k | AccumWidth = AccumAlign = 32; |
81 | 101k | LongAccumWidth = LongAccumAlign = 64; |
82 | 101k | ShortFractWidth = ShortFractAlign = 8; |
83 | 101k | FractWidth = FractAlign = 16; |
84 | 101k | LongFractWidth = LongFractAlign = 32; |
85 | | |
86 | | // Fixed point default integral and fractional bit sizes |
87 | | // We give the _Accum 1 fewer fractional bits than their corresponding _Fract |
88 | | // types by default to have the same number of fractional bits between _Accum |
89 | | // and _Fract types. |
90 | 101k | PaddingOnUnsignedFixedPoint = false; |
91 | 101k | ShortAccumScale = 7; |
92 | 101k | AccumScale = 15; |
93 | 101k | LongAccumScale = 31; |
94 | | |
95 | 101k | SuitableAlign = 64; |
96 | 101k | DefaultAlignForAttributeAligned = 128; |
97 | 101k | MinGlobalAlign = 0; |
98 | | // From the glibc documentation, on GNU systems, malloc guarantees 16-byte |
99 | | // alignment on 64-bit systems and 8-byte alignment on 32-bit systems. See |
100 | | // https://www.gnu.org/software/libc/manual/html_node/Malloc-Examples.html. |
101 | | // This alignment guarantee also applies to Windows and Android. On Darwin |
102 | | // and OpenBSD, the alignment is 16 bytes on both 64-bit and 32-bit systems. |
103 | 101k | if (T.isGNUEnvironment() || T.isWindowsMSVCEnvironment()94.1k || T.isAndroid()84.9k || |
104 | 101k | T.isOHOSFamily()84.9k ) |
105 | 16.5k | NewAlign = Triple.isArch64Bit() ? 12814.9k : Triple.isArch32Bit()1.63k ? 641.63k : 01 ; |
106 | 84.9k | else if (T.isOSDarwin() || T.isOSOpenBSD()25.0k ) |
107 | 59.9k | NewAlign = 128; |
108 | 25.0k | else |
109 | 25.0k | NewAlign = 0; // Infer from basic type alignment. |
110 | 101k | HalfWidth = 16; |
111 | 101k | HalfAlign = 16; |
112 | 101k | FloatWidth = 32; |
113 | 101k | FloatAlign = 32; |
114 | 101k | DoubleWidth = 64; |
115 | 101k | DoubleAlign = 64; |
116 | 101k | LongDoubleWidth = 64; |
117 | 101k | LongDoubleAlign = 64; |
118 | 101k | Float128Align = 128; |
119 | 101k | Ibm128Align = 128; |
120 | 101k | LargeArrayMinWidth = 0; |
121 | 101k | LargeArrayAlign = 0; |
122 | 101k | MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0; |
123 | 101k | MaxVectorAlign = 0; |
124 | 101k | MaxTLSAlign = 0; |
125 | 101k | SizeType = UnsignedLong; |
126 | 101k | PtrDiffType = SignedLong; |
127 | 101k | IntMaxType = SignedLongLong; |
128 | 101k | IntPtrType = SignedLong; |
129 | 101k | WCharType = SignedInt; |
130 | 101k | WIntType = SignedInt; |
131 | 101k | Char16Type = UnsignedShort; |
132 | 101k | Char32Type = UnsignedInt; |
133 | 101k | Int64Type = SignedLongLong; |
134 | 101k | Int16Type = SignedShort; |
135 | 101k | SigAtomicType = SignedInt; |
136 | 101k | ProcessIDType = SignedInt; |
137 | 101k | UseSignedCharForObjCBool = true; |
138 | 101k | UseBitFieldTypeAlignment = true; |
139 | 101k | UseZeroLengthBitfieldAlignment = false; |
140 | 101k | UseLeadingZeroLengthBitfield = true; |
141 | 101k | UseExplicitBitFieldAlignment = true; |
142 | 101k | ZeroLengthBitfieldBoundary = 0; |
143 | 101k | MaxAlignedAttribute = 0; |
144 | 101k | HalfFormat = &llvm::APFloat::IEEEhalf(); |
145 | 101k | FloatFormat = &llvm::APFloat::IEEEsingle(); |
146 | 101k | DoubleFormat = &llvm::APFloat::IEEEdouble(); |
147 | 101k | LongDoubleFormat = &llvm::APFloat::IEEEdouble(); |
148 | 101k | Float128Format = &llvm::APFloat::IEEEquad(); |
149 | 101k | Ibm128Format = &llvm::APFloat::PPCDoubleDouble(); |
150 | 101k | MCountName = "mcount"; |
151 | 101k | UserLabelPrefix = "_"; |
152 | 101k | RegParmMax = 0; |
153 | 101k | SSERegParmMax = 0; |
154 | 101k | HasAlignMac68kSupport = false; |
155 | 101k | HasBuiltinMSVaList = false; |
156 | 101k | IsRenderScriptTarget = false; |
157 | 101k | HasAArch64SVETypes = false; |
158 | 101k | HasRISCVVTypes = false; |
159 | 101k | AllowAMDGPUUnsafeFPAtomics = false; |
160 | 101k | ARMCDECoprocMask = 0; |
161 | | |
162 | | // Default to no types using fpret. |
163 | 101k | RealTypeUsesObjCFPRetMask = 0; |
164 | | |
165 | | // Default to not using fp2ret for __Complex long double |
166 | 101k | ComplexLongDoubleUsesFP2Ret = false; |
167 | | |
168 | | // Set the C++ ABI based on the triple. |
169 | 101k | TheCXXABI.set(Triple.isKnownWindowsMSVCEnvironment() |
170 | 101k | ? TargetCXXABI::Microsoft9.12k |
171 | 101k | : TargetCXXABI::GenericItanium92.3k ); |
172 | | |
173 | | // Default to an empty address space map. |
174 | 101k | AddrSpaceMap = &DefaultAddrSpaceMap; |
175 | 101k | UseAddrSpaceMapMangling = false; |
176 | | |
177 | | // Default to an unknown platform name. |
178 | 101k | PlatformName = "unknown"; |
179 | 101k | PlatformMinVersion = VersionTuple(); |
180 | | |
181 | 101k | MaxOpenCLWorkGroupSize = 1024; |
182 | | |
183 | 101k | MaxBitIntWidth.reset(); |
184 | 101k | } |
185 | | |
186 | | // Out of line virtual dtor for TargetInfo. |
187 | 94.9k | TargetInfo::~TargetInfo() {} |
188 | | |
189 | 162k | void TargetInfo::resetDataLayout(StringRef DL, const char *ULP) { |
190 | 162k | DataLayoutString = DL.str(); |
191 | 162k | UserLabelPrefix = ULP; |
192 | 162k | } |
193 | | |
194 | | bool |
195 | 1 | TargetInfo::checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const { |
196 | 1 | Diags.Report(diag::err_opt_not_valid_on_target) << "cf-protection=branch"; |
197 | 1 | return false; |
198 | 1 | } |
199 | | |
200 | | bool |
201 | 0 | TargetInfo::checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const { |
202 | 0 | Diags.Report(diag::err_opt_not_valid_on_target) << "cf-protection=return"; |
203 | 0 | return false; |
204 | 0 | } |
205 | | |
206 | | /// getTypeName - Return the user string for the specified integer type enum. |
207 | | /// For example, SignedShort -> "short". |
208 | 3.19M | const char *TargetInfo::getTypeName(IntType T) { |
209 | 3.19M | switch (T) { |
210 | 0 | default: llvm_unreachable("not an integer!"); |
211 | 281k | case SignedChar: return "signed char"; |
212 | 282k | case UnsignedChar: return "unsigned char"; |
213 | 281k | case SignedShort: return "short"; |
214 | 394k | case UnsignedShort: return "unsigned short"; |
215 | 472k | case SignedInt: return "int"; |
216 | 423k | case UnsignedInt: return "unsigned int"; |
217 | 247k | case SignedLong: return "long int"; |
218 | 247k | case UnsignedLong: return "long unsigned int"; |
219 | 283k | case SignedLongLong: return "long long int"; |
220 | 283k | case UnsignedLongLong: return "long long unsigned int"; |
221 | 3.19M | } |
222 | 3.19M | } |
223 | | |
224 | | /// getTypeConstantSuffix - Return the constant suffix for the specified |
225 | | /// integer type enum. For example, SignedLong -> "L". |
226 | 4.58M | const char *TargetInfo::getTypeConstantSuffix(IntType T) const { |
227 | 4.58M | switch (T) { |
228 | 0 | default: llvm_unreachable("not an integer!"); |
229 | 470k | case SignedChar: |
230 | 939k | case SignedShort: |
231 | 1.69M | case SignedInt: return ""; |
232 | 421k | case SignedLong: return "L"; |
233 | 485k | case SignedLongLong: return "LL"; |
234 | 376k | case UnsignedChar: |
235 | 376k | if (getCharWidth() < getIntWidth()) |
236 | 376k | return ""; |
237 | 376k | [[fallthrough]];0 |
238 | 394k | case UnsignedShort: |
239 | 394k | if (getShortWidth() < getIntWidth()) |
240 | 394k | return ""; |
241 | 394k | [[fallthrough]];90 |
242 | 436k | case UnsignedInt: return "U"; |
243 | 378k | case UnsignedLong: return "UL"; |
244 | 398k | case UnsignedLongLong: return "ULL"; |
245 | 4.58M | } |
246 | 4.58M | } |
247 | | |
248 | | /// getTypeFormatModifier - Return the printf format modifier for the |
249 | | /// specified integer type enum. For example, SignedLong -> "l". |
250 | | |
251 | 2.82M | const char *TargetInfo::getTypeFormatModifier(IntType T) { |
252 | 2.82M | switch (T) { |
253 | 0 | default: llvm_unreachable("not an integer!"); |
254 | 281k | case SignedChar: |
255 | 563k | case UnsignedChar: return "hh"; |
256 | 281k | case SignedShort: |
257 | 563k | case UnsignedShort: return "h"; |
258 | 316k | case SignedInt: |
259 | 633k | case UnsignedInt: return ""; |
260 | 247k | case SignedLong: |
261 | 494k | case UnsignedLong: return "l"; |
262 | 283k | case SignedLongLong: |
263 | 566k | case UnsignedLongLong: return "ll"; |
264 | 2.82M | } |
265 | 2.82M | } |
266 | | |
267 | | /// getTypeWidth - Return the width (in bits) of the specified integer type |
268 | | /// enum. For example, SignedInt -> getIntWidth(). |
269 | 19.4M | unsigned TargetInfo::getTypeWidth(IntType T) const { |
270 | 19.4M | switch (T) { |
271 | 0 | default: llvm_unreachable("not an integer!"); |
272 | 752k | case SignedChar: |
273 | 1.22M | case UnsignedChar: return getCharWidth(); |
274 | 751k | case SignedShort: |
275 | 1.42M | case UnsignedShort: return getShortWidth(); |
276 | 2.33M | case SignedInt: |
277 | 3.34M | case UnsignedInt: return getIntWidth(); |
278 | 8.00M | case SignedLong: |
279 | 11.5M | case UnsignedLong: return getLongWidth(); |
280 | 1.36M | case SignedLongLong: |
281 | 1.83M | case UnsignedLongLong: return getLongLongWidth(); |
282 | 19.4M | }; |
283 | 0 | } |
284 | | |
285 | | TargetInfo::IntType TargetInfo::getIntTypeByWidth( |
286 | 1.35M | unsigned BitWidth, bool IsSigned) const { |
287 | 1.35M | if (getCharWidth() == BitWidth) |
288 | 66.1k | return IsSigned ? SignedChar33.7k : UnsignedChar32.3k ; |
289 | 1.28M | if (getShortWidth() == BitWidth) |
290 | 75.2k | return IsSigned ? SignedShort39.9k : UnsignedShort35.2k ; |
291 | 1.21M | if (getIntWidth() == BitWidth) |
292 | 699k | return IsSigned ? SignedInt646k : UnsignedInt52.7k ; |
293 | 515k | if (getLongWidth() == BitWidth) |
294 | 509k | return IsSigned ? SignedLong310k : UnsignedLong199k ; |
295 | 5.45k | if (getLongLongWidth() == BitWidth) |
296 | 5.42k | return IsSigned ? SignedLongLong5.34k : UnsignedLongLong80 ; |
297 | 37 | return NoInt; |
298 | 5.45k | } |
299 | | |
300 | | TargetInfo::IntType TargetInfo::getLeastIntTypeByWidth(unsigned BitWidth, |
301 | 1.29M | bool IsSigned) const { |
302 | 1.29M | if (getCharWidth() >= BitWidth) |
303 | 375k | return IsSigned ? SignedChar187k : UnsignedChar187k ; |
304 | 915k | if (getShortWidth() >= BitWidth) |
305 | 375k | return IsSigned ? SignedShort187k : UnsignedShort187k ; |
306 | 539k | if (getIntWidth() >= BitWidth) |
307 | 375k | return IsSigned ? SignedInt187k : UnsignedInt187k ; |
308 | 163k | if (getLongWidth() >= BitWidth) |
309 | 60.8k | return IsSigned ? SignedLong30.4k : UnsignedLong30.4k ; |
310 | 102k | if (getLongLongWidth() >= BitWidth) |
311 | 102k | return IsSigned ? SignedLongLong51.4k : UnsignedLongLong51.4k ; |
312 | 33 | return NoInt; |
313 | 102k | } |
314 | | |
315 | | FloatModeKind TargetInfo::getRealTypeByWidth(unsigned BitWidth, |
316 | 106 | FloatModeKind ExplicitType) const { |
317 | 106 | if (getHalfWidth() == BitWidth) |
318 | 21 | return FloatModeKind::Half; |
319 | 85 | if (getFloatWidth() == BitWidth) |
320 | 30 | return FloatModeKind::Float; |
321 | 55 | if (getDoubleWidth() == BitWidth) |
322 | 35 | return FloatModeKind::Double; |
323 | | |
324 | 20 | switch (BitWidth) { |
325 | 5 | case 96: |
326 | 5 | if (&getLongDoubleFormat() == &llvm::APFloat::x87DoubleExtended()) |
327 | 5 | return FloatModeKind::LongDouble; |
328 | 0 | break; |
329 | 14 | case 128: |
330 | | // The caller explicitly asked for an IEEE compliant type but we still |
331 | | // have to check if the target supports it. |
332 | 14 | if (ExplicitType == FloatModeKind::Float128) |
333 | 3 | return hasFloat128Type() ? FloatModeKind::Float128 |
334 | 3 | : FloatModeKind::NoFloat0 ; |
335 | 11 | if (ExplicitType == FloatModeKind::Ibm128) |
336 | 6 | return hasIbm128Type() ? FloatModeKind::Ibm128 |
337 | 6 | : FloatModeKind::NoFloat0 ; |
338 | 5 | if (&getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble() || |
339 | 5 | &getLongDoubleFormat() == &llvm::APFloat::IEEEquad()3 ) |
340 | 2 | return FloatModeKind::LongDouble; |
341 | 3 | if (hasFloat128Type()) |
342 | 3 | return FloatModeKind::Float128; |
343 | 0 | break; |
344 | 20 | } |
345 | | |
346 | 1 | return FloatModeKind::NoFloat; |
347 | 20 | } |
348 | | |
349 | | /// getTypeAlign - Return the alignment (in bits) of the specified integer type |
350 | | /// enum. For example, SignedInt -> getIntAlign(). |
351 | 26.9k | unsigned TargetInfo::getTypeAlign(IntType T) const { |
352 | 26.9k | switch (T) { |
353 | 0 | default: llvm_unreachable("not an integer!"); |
354 | 0 | case SignedChar: |
355 | 1 | case UnsignedChar: return getCharAlign(); |
356 | 0 | case SignedShort: |
357 | 1.28k | case UnsignedShort: return getShortAlign(); |
358 | 23.3k | case SignedInt: |
359 | 25.1k | case UnsignedInt: return getIntAlign(); |
360 | 539 | case SignedLong: |
361 | 539 | case UnsignedLong: return getLongAlign(); |
362 | 55 | case SignedLongLong: |
363 | 55 | case UnsignedLongLong: return getLongLongAlign(); |
364 | 26.9k | }; |
365 | 0 | } |
366 | | |
367 | | /// isTypeSigned - Return whether an integer types is signed. Returns true if |
368 | | /// the type is signed; false otherwise. |
369 | 8.18M | bool TargetInfo::isTypeSigned(IntType T) { |
370 | 8.18M | switch (T) { |
371 | 0 | default: llvm_unreachable("not an integer!"); |
372 | 846k | case SignedChar: |
373 | 1.69M | case SignedShort: |
374 | 3.09M | case SignedInt: |
375 | 3.82M | case SignedLong: |
376 | 4.53M | case SignedLongLong: |
377 | 4.53M | return true; |
378 | 752k | case UnsignedChar: |
379 | 1.55M | case UnsignedShort: |
380 | 2.40M | case UnsignedInt: |
381 | 3.03M | case UnsignedLong: |
382 | 3.65M | case UnsignedLongLong: |
383 | 3.65M | return false; |
384 | 8.18M | }; |
385 | 0 | } |
386 | | |
387 | | /// adjust - Set forced language options. |
388 | | /// Apply changes to the target information with respect to certain |
389 | | /// language options which change the target configuration and adjust |
390 | | /// the language based on the target options where applicable. |
391 | 188k | void TargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) { |
392 | 188k | if (Opts.NoBitFieldTypeAlign) |
393 | 2 | UseBitFieldTypeAlignment = false; |
394 | | |
395 | 188k | switch (Opts.WCharSize) { |
396 | 0 | default: llvm_unreachable("invalid wchar_t width"); |
397 | 188k | case 0: break; |
398 | 2 | case 1: WCharType = Opts.WCharIsSigned ? SignedChar0 : UnsignedChar; break; |
399 | 56 | case 2: WCharType = Opts.WCharIsSigned ? SignedShort0 : UnsignedShort; break; |
400 | 18 | case 4: WCharType = Opts.WCharIsSigned ? SignedInt14 : UnsignedInt4 ; break; |
401 | 188k | } |
402 | | |
403 | 188k | if (Opts.AlignDouble) { |
404 | 8 | DoubleAlign = LongLongAlign = 64; |
405 | 8 | LongDoubleAlign = 64; |
406 | 8 | } |
407 | | |
408 | 188k | if (Opts.OpenCL) { |
409 | | // OpenCL C requires specific widths for types, irrespective of |
410 | | // what these normally are for the target. |
411 | | // We also define long long and long double here, although the |
412 | | // OpenCL standard only mentions these as "reserved". |
413 | 2.00k | IntWidth = IntAlign = 32; |
414 | 2.00k | LongWidth = LongAlign = 64; |
415 | 2.00k | LongLongWidth = LongLongAlign = 128; |
416 | 2.00k | HalfWidth = HalfAlign = 16; |
417 | 2.00k | FloatWidth = FloatAlign = 32; |
418 | | |
419 | | // Embedded 32-bit targets (OpenCL EP) might have double C type |
420 | | // defined as float. Let's not override this as it might lead |
421 | | // to generating illegal code that uses 64bit doubles. |
422 | 2.00k | if (DoubleWidth != FloatWidth) { |
423 | 2.00k | DoubleWidth = DoubleAlign = 64; |
424 | 2.00k | DoubleFormat = &llvm::APFloat::IEEEdouble(); |
425 | 2.00k | } |
426 | 2.00k | LongDoubleWidth = LongDoubleAlign = 128; |
427 | | |
428 | 2.00k | unsigned MaxPointerWidth = getMaxPointerWidth(); |
429 | 2.00k | assert(MaxPointerWidth == 32 || MaxPointerWidth == 64); |
430 | 2.00k | bool Is32BitArch = MaxPointerWidth == 32; |
431 | 2.00k | SizeType = Is32BitArch ? UnsignedInt632 : UnsignedLong1.37k ; |
432 | 2.00k | PtrDiffType = Is32BitArch ? SignedInt632 : SignedLong1.37k ; |
433 | 2.00k | IntPtrType = Is32BitArch ? SignedInt632 : SignedLong1.37k ; |
434 | | |
435 | 2.00k | IntMaxType = SignedLongLong; |
436 | 2.00k | Int64Type = SignedLong; |
437 | | |
438 | 2.00k | HalfFormat = &llvm::APFloat::IEEEhalf(); |
439 | 2.00k | FloatFormat = &llvm::APFloat::IEEEsingle(); |
440 | 2.00k | LongDoubleFormat = &llvm::APFloat::IEEEquad(); |
441 | | |
442 | | // OpenCL C v3.0 s6.7.5 - The generic address space requires support for |
443 | | // OpenCL C 2.0 or OpenCL C 3.0 with the __opencl_c_generic_address_space |
444 | | // feature |
445 | | // OpenCL C v3.0 s6.2.1 - OpenCL pipes require support of OpenCL C 2.0 |
446 | | // or later and __opencl_c_pipes feature |
447 | | // FIXME: These language options are also defined in setLangDefaults() |
448 | | // for OpenCL C 2.0 but with no access to target capabilities. Target |
449 | | // should be immutable once created and thus these language options need |
450 | | // to be defined only once. |
451 | 2.00k | if (Opts.getOpenCLCompatibleVersion() == 300) { |
452 | 278 | const auto &OpenCLFeaturesMap = getSupportedOpenCLOpts(); |
453 | 278 | Opts.OpenCLGenericAddressSpace = hasFeatureEnabled( |
454 | 278 | OpenCLFeaturesMap, "__opencl_c_generic_address_space"); |
455 | 278 | Opts.OpenCLPipes = |
456 | 278 | hasFeatureEnabled(OpenCLFeaturesMap, "__opencl_c_pipes"); |
457 | 278 | Opts.Blocks = |
458 | 278 | hasFeatureEnabled(OpenCLFeaturesMap, "__opencl_c_device_enqueue"); |
459 | 278 | } |
460 | 2.00k | } |
461 | | |
462 | 188k | if (Opts.DoubleSize) { |
463 | 4 | if (Opts.DoubleSize == 32) { |
464 | 2 | DoubleWidth = 32; |
465 | 2 | LongDoubleWidth = 32; |
466 | 2 | DoubleFormat = &llvm::APFloat::IEEEsingle(); |
467 | 2 | LongDoubleFormat = &llvm::APFloat::IEEEsingle(); |
468 | 2 | } else if (Opts.DoubleSize == 64) { |
469 | 2 | DoubleWidth = 64; |
470 | 2 | LongDoubleWidth = 64; |
471 | 2 | DoubleFormat = &llvm::APFloat::IEEEdouble(); |
472 | 2 | LongDoubleFormat = &llvm::APFloat::IEEEdouble(); |
473 | 2 | } |
474 | 4 | } |
475 | | |
476 | 188k | if (Opts.LongDoubleSize) { |
477 | 52 | if (Opts.LongDoubleSize == DoubleWidth) { |
478 | 26 | LongDoubleWidth = DoubleWidth; |
479 | 26 | LongDoubleAlign = DoubleAlign; |
480 | 26 | LongDoubleFormat = DoubleFormat; |
481 | 26 | } else if (Opts.LongDoubleSize == 128) { |
482 | 16 | LongDoubleWidth = LongDoubleAlign = 128; |
483 | 16 | LongDoubleFormat = &llvm::APFloat::IEEEquad(); |
484 | 16 | } else if (10 Opts.LongDoubleSize == 8010 ) { |
485 | 10 | LongDoubleFormat = &llvm::APFloat::x87DoubleExtended(); |
486 | 10 | if (getTriple().isWindowsMSVCEnvironment()) { |
487 | 4 | LongDoubleWidth = 128; |
488 | 4 | LongDoubleAlign = 128; |
489 | 6 | } else { // Linux |
490 | 6 | if (getTriple().getArch() == llvm::Triple::x86) { |
491 | 4 | LongDoubleWidth = 96; |
492 | 4 | LongDoubleAlign = 32; |
493 | 4 | } else { |
494 | 2 | LongDoubleWidth = 128; |
495 | 2 | LongDoubleAlign = 128; |
496 | 2 | } |
497 | 6 | } |
498 | 10 | } |
499 | 52 | } |
500 | | |
501 | 188k | if (Opts.NewAlignOverride) |
502 | 6 | NewAlign = Opts.NewAlignOverride * getCharWidth(); |
503 | | |
504 | | // Each unsigned fixed point type has the same number of fractional bits as |
505 | | // its corresponding signed type. |
506 | 188k | PaddingOnUnsignedFixedPoint |= Opts.PaddingOnUnsignedFixedPoint; |
507 | 188k | CheckFixedPointBits(); |
508 | | |
509 | 188k | if (Opts.ProtectParens && !checkArithmeticFenceSupported()23 ) { |
510 | 1 | Diags.Report(diag::err_opt_not_valid_on_target) << "-fprotect-parens"; |
511 | 1 | Opts.ProtectParens = false; |
512 | 1 | } |
513 | | |
514 | 188k | if (Opts.MaxBitIntWidth) |
515 | 26.1k | MaxBitIntWidth = static_cast<unsigned>(Opts.MaxBitIntWidth); |
516 | | |
517 | 188k | if (Opts.FakeAddressSpaceMap) |
518 | 100 | AddrSpaceMap = &FakeAddrSpaceMap; |
519 | 188k | } |
520 | | |
521 | | bool TargetInfo::initFeatureMap( |
522 | | llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, |
523 | 2.64M | const std::vector<std::string> &FeatureVec) const { |
524 | 27.7M | for (const auto &F : FeatureVec) { |
525 | 27.7M | StringRef Name = F; |
526 | 27.7M | if (Name.empty()) |
527 | 2 | continue; |
528 | | // Apply the feature via the target. |
529 | 27.7M | if (Name[0] != '+' && Name[0] != '-'72.2k ) |
530 | 2 | Diags.Report(diag::warn_fe_backend_invalid_feature_flag) << Name; |
531 | 27.7M | else |
532 | 27.7M | setFeatureEnabled(Features, Name.substr(1), Name[0] == '+'); |
533 | 27.7M | } |
534 | 2.64M | return true; |
535 | 2.64M | } |
536 | | |
537 | 1.69M | ParsedTargetAttr TargetInfo::parseTargetAttr(StringRef Features) const { |
538 | 1.69M | ParsedTargetAttr Ret; |
539 | 1.69M | if (Features == "default") |
540 | 558 | return Ret; |
541 | 1.69M | SmallVector<StringRef, 1> AttrFeatures; |
542 | 1.69M | Features.split(AttrFeatures, ","); |
543 | | |
544 | | // Grab the various features and prepend a "+" to turn on the feature to |
545 | | // the backend and add them to our existing set of features. |
546 | 3.56M | for (auto &Feature : AttrFeatures) { |
547 | | // Go ahead and trim whitespace rather than either erroring or |
548 | | // accepting it weirdly. |
549 | 3.56M | Feature = Feature.trim(); |
550 | | |
551 | | // TODO: Support the fpmath option. It will require checking |
552 | | // overall feature validity for the function with the rest of the |
553 | | // attributes on the function. |
554 | 3.56M | if (Feature.startswith("fpmath=")) |
555 | 0 | continue; |
556 | | |
557 | 3.56M | if (Feature.startswith("branch-protection=")) { |
558 | 90 | Ret.BranchProtection = Feature.split('=').second.trim(); |
559 | 90 | continue; |
560 | 90 | } |
561 | | |
562 | | // While we're here iterating check for a different target cpu. |
563 | 3.56M | if (Feature.startswith("arch=")) { |
564 | 2.06k | if (!Ret.CPU.empty()) |
565 | 7 | Ret.Duplicate = "arch="; |
566 | 2.05k | else |
567 | 2.05k | Ret.CPU = Feature.split("=").second.trim(); |
568 | 3.56M | } else if (Feature.startswith("tune=")) { |
569 | 14 | if (!Ret.Tune.empty()) |
570 | 3 | Ret.Duplicate = "tune="; |
571 | 11 | else |
572 | 11 | Ret.Tune = Feature.split("=").second.trim(); |
573 | 3.56M | } else if (Feature.startswith("no-")) |
574 | 1.07M | Ret.Features.push_back("-" + Feature.split("-").second.str()); |
575 | 2.48M | else |
576 | 2.48M | Ret.Features.push_back("+" + Feature.str()); |
577 | 3.56M | } |
578 | 1.69M | return Ret; |
579 | 1.69M | } |
580 | | |
581 | | TargetInfo::CallingConvKind |
582 | 1.42M | TargetInfo::getCallingConvKind(bool ClangABICompat4) const { |
583 | 1.42M | if (getCXXABI() != TargetCXXABI::Microsoft && |
584 | 1.42M | (1.42M ClangABICompat41.42M || getTriple().isPS4()1.42M )) |
585 | 1.07k | return CCK_ClangABI4OrPS4; |
586 | 1.42M | return CCK_Default; |
587 | 1.42M | } |
588 | | |
589 | 2.12k | bool TargetInfo::areDefaultedSMFStillPOD(const LangOptions &LangOpts) const { |
590 | 2.12k | return LangOpts.getClangABICompat() > LangOptions::ClangABI::Ver15; |
591 | 2.12k | } |
592 | | |
593 | 178 | LangAS TargetInfo::getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const { |
594 | 178 | switch (TK) { |
595 | 41 | case OCLTK_Image: |
596 | 77 | case OCLTK_Pipe: |
597 | 77 | return LangAS::opencl_global; |
598 | | |
599 | 18 | case OCLTK_Sampler: |
600 | 18 | return LangAS::opencl_constant; |
601 | | |
602 | 83 | default: |
603 | 83 | return LangAS::Default; |
604 | 178 | } |
605 | 178 | } |
606 | | |
607 | | //===----------------------------------------------------------------------===// |
608 | | |
609 | | |
610 | 9.26k | static StringRef removeGCCRegisterPrefix(StringRef Name) { |
611 | 9.26k | if (Name[0] == '%' || Name[0] == '#'8.68k ) |
612 | 600 | Name = Name.substr(1); |
613 | | |
614 | 9.26k | return Name; |
615 | 9.26k | } |
616 | | |
617 | | /// isValidClobber - Returns whether the passed in string is |
618 | | /// a valid clobber in an inline asm statement. This is used by |
619 | | /// Sema. |
620 | 3.54k | bool TargetInfo::isValidClobber(StringRef Name) const { |
621 | 3.54k | return (isValidGCCRegisterName(Name) || Name == "memory"2.29k || Name == "cc"1.35k || |
622 | 3.54k | Name == "unwind"7 ); |
623 | 3.54k | } |
624 | | |
625 | | /// isValidGCCRegisterName - Returns whether the passed in string |
626 | | /// is a valid register name according to GCC. This is used by Sema for |
627 | | /// inline asm statements. |
628 | 6.62k | bool TargetInfo::isValidGCCRegisterName(StringRef Name) const { |
629 | 6.62k | if (Name.empty()) |
630 | 0 | return false; |
631 | | |
632 | | // Get rid of any register prefix. |
633 | 6.62k | Name = removeGCCRegisterPrefix(Name); |
634 | 6.62k | if (Name.empty()) |
635 | 1 | return false; |
636 | | |
637 | 6.62k | ArrayRef<const char *> Names = getGCCRegNames(); |
638 | | |
639 | | // If we have a number it maps to an entry in the register name array. |
640 | 6.62k | if (isDigit(Name[0])) { |
641 | 26 | unsigned n; |
642 | 26 | if (!Name.getAsInteger(0, n)) |
643 | 26 | return n < Names.size(); |
644 | 26 | } |
645 | | |
646 | | // Check register names. |
647 | 6.59k | if (llvm::is_contained(Names, Name)) |
648 | 3.28k | return true; |
649 | | |
650 | | // Check any additional names that we have. |
651 | 3.31k | for (const AddlRegName &ARN : getGCCAddlRegNames()) |
652 | 148k | for (const char *AN : ARN.Names)37.2k { |
653 | 148k | if (!AN) |
654 | 36.8k | break; |
655 | | // Make sure the register that the additional name is for is within |
656 | | // the bounds of the register names from above. |
657 | 111k | if (AN == Name && ARN.RegNum < Names.size()389 ) |
658 | 389 | return true; |
659 | 111k | } |
660 | | |
661 | | // Now check aliases. |
662 | 2.92k | for (const GCCRegAlias &GRA : getGCCRegAliases()) |
663 | 39.8k | for (const char *A : GRA.Aliases)16.9k { |
664 | 39.8k | if (!A) |
665 | 16.2k | break; |
666 | 23.6k | if (A == Name) |
667 | 621 | return true; |
668 | 23.6k | } |
669 | | |
670 | 2.30k | return false; |
671 | 2.92k | } |
672 | | |
673 | | StringRef TargetInfo::getNormalizedGCCRegisterName(StringRef Name, |
674 | 2.64k | bool ReturnCanonical) const { |
675 | 2.64k | assert(isValidGCCRegisterName(Name) && "Invalid register passed in"); |
676 | | |
677 | | // Get rid of any register prefix. |
678 | 2.64k | Name = removeGCCRegisterPrefix(Name); |
679 | | |
680 | 2.64k | ArrayRef<const char *> Names = getGCCRegNames(); |
681 | | |
682 | | // First, check if we have a number. |
683 | 2.64k | if (isDigit(Name[0])) { |
684 | 12 | unsigned n; |
685 | 12 | if (!Name.getAsInteger(0, n)) { |
686 | 12 | assert(n < Names.size() && "Out of bounds register number!"); |
687 | 12 | return Names[n]; |
688 | 12 | } |
689 | 12 | } |
690 | | |
691 | | // Check any additional names that we have. |
692 | 2.62k | for (const AddlRegName &ARN : getGCCAddlRegNames()) |
693 | 21.5k | for (const char *AN : ARN.Names)5.58k { |
694 | 21.5k | if (!AN) |
695 | 5.32k | break; |
696 | | // Make sure the register that the additional name is for is within |
697 | | // the bounds of the register names from above. |
698 | 16.1k | if (AN == Name && ARN.RegNum < Names.size()254 ) |
699 | 254 | return ReturnCanonical ? Names[ARN.RegNum]59 : Name195 ; |
700 | 16.1k | } |
701 | | |
702 | | // Now check aliases. |
703 | 2.37k | for (const GCCRegAlias &RA : getGCCRegAliases()) |
704 | 118k | for (const char *A : RA.Aliases)55.9k { |
705 | 118k | if (!A) |
706 | 55.5k | break; |
707 | 63.4k | if (A == Name) |
708 | 310 | return RA.Register; |
709 | 63.4k | } |
710 | | |
711 | 2.06k | return Name; |
712 | 2.37k | } |
713 | | |
714 | 9.57k | bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const { |
715 | 9.57k | const char *Name = Info.getConstraintStr().c_str(); |
716 | | // An output constraint must start with '=' or '+' |
717 | 9.57k | if (*Name != '=' && *Name != '+'931 ) |
718 | 118 | return false; |
719 | | |
720 | 9.45k | if (*Name == '+') |
721 | 813 | Info.setIsReadWrite(); |
722 | | |
723 | 9.45k | Name++; |
724 | 20.2k | while (*Name) { |
725 | 10.8k | switch (*Name) { |
726 | 6.64k | default: |
727 | 6.64k | if (!validateAsmConstraint(Name, Info)) { |
728 | | // FIXME: We temporarily return false |
729 | | // so we can add more constraints as we hit it. |
730 | | // Eventually, an unknown constraint should just be treated as 'g'. |
731 | 38 | return false; |
732 | 38 | } |
733 | 6.60k | break; |
734 | 6.60k | case '&': // early clobber. |
735 | 70 | Info.setEarlyClobber(); |
736 | 70 | break; |
737 | 7 | case '%': // commutative. |
738 | | // FIXME: Check that there is a another register after this one. |
739 | 7 | break; |
740 | 2.90k | case 'r': // general register. |
741 | 2.90k | Info.setAllowsRegister(); |
742 | 2.90k | break; |
743 | 528 | case 'm': // memory operand. |
744 | 528 | case 'o': // offsetable memory operand. |
745 | 528 | case 'V': // non-offsetable memory operand. |
746 | 528 | case '<': // autodecrement memory operand. |
747 | 528 | case '>': // autoincrement memory operand. |
748 | 528 | Info.setAllowsMemory(); |
749 | 528 | break; |
750 | 32 | case 'g': // general register, memory operand or immediate integer. |
751 | 32 | case 'X': // any operand. |
752 | 32 | Info.setAllowsRegister(); |
753 | 32 | Info.setAllowsMemory(); |
754 | 32 | break; |
755 | 648 | case ',': // multiple alternative constraint. Pass it. |
756 | | // Handle additional optional '=' or '+' modifiers. |
757 | 648 | if (Name[1] == '=' || Name[1] == '+'643 ) |
758 | 5 | Name++; |
759 | 648 | break; |
760 | 2 | case '#': // Ignore as constraint. |
761 | 3 | while (Name[1] && Name[1] != ','1 ) |
762 | 1 | Name++; |
763 | 2 | break; |
764 | 1 | case '?': // Disparage slightly code. |
765 | 2 | case '!': // Disparage severely. |
766 | 3 | case '*': // Ignore for choosing register preferences. |
767 | 12 | case 'i': // Ignore i,n,E,F as output constraints (match from the other |
768 | | // chars) |
769 | 21 | case 'n': |
770 | 30 | case 'E': |
771 | 39 | case 'F': |
772 | 39 | break; // Pass them. |
773 | 10.8k | } |
774 | | |
775 | 10.8k | Name++; |
776 | 10.8k | } |
777 | | |
778 | | // Early clobber with a read-write constraint which doesn't permit registers |
779 | | // is invalid. |
780 | 9.41k | if (Info.earlyClobber() && Info.isReadWrite()67 && !Info.allowsRegister()7 ) |
781 | 1 | return false; |
782 | | |
783 | | // If a constraint allows neither memory nor register operands it contains |
784 | | // only modifiers. Reject it. |
785 | 9.41k | return Info.allowsMemory() || Info.allowsRegister()8.88k ; |
786 | 9.41k | } |
787 | | |
788 | | bool TargetInfo::resolveSymbolicName(const char *&Name, |
789 | | ArrayRef<ConstraintInfo> OutputConstraints, |
790 | 52 | unsigned &Index) const { |
791 | 52 | assert(*Name == '[' && "Symbolic name did not start with '['"); |
792 | 52 | Name++; |
793 | 52 | const char *Start = Name; |
794 | 247 | while (*Name && *Name != ']'245 ) |
795 | 195 | Name++; |
796 | | |
797 | 52 | if (!*Name) { |
798 | | // Missing ']' |
799 | 2 | return false; |
800 | 2 | } |
801 | | |
802 | 50 | std::string SymbolicName(Start, Name - Start); |
803 | | |
804 | 183 | for (Index = 0; Index != OutputConstraints.size(); ++Index133 ) |
805 | 182 | if (SymbolicName == OutputConstraints[Index].getName()) |
806 | 49 | return true; |
807 | | |
808 | 1 | return false; |
809 | 50 | } |
810 | | |
811 | | bool TargetInfo::validateInputConstraint( |
812 | | MutableArrayRef<ConstraintInfo> OutputConstraints, |
813 | 11.9k | ConstraintInfo &Info) const { |
814 | 11.9k | const char *Name = Info.ConstraintStr.c_str(); |
815 | | |
816 | 11.9k | if (!*Name) |
817 | 2 | return false; |
818 | | |
819 | 25.3k | while (11.9k *Name) { |
820 | 13.4k | switch (*Name) { |
821 | 6.84k | default: |
822 | | // Check if we have a matching constraint |
823 | 6.84k | if (*Name >= '0' && *Name <= '9') { |
824 | 167 | const char *DigitStart = Name; |
825 | 168 | while (Name[1] >= '0' && Name[1] <= '9'3 ) |
826 | 1 | Name++; |
827 | 167 | const char *DigitEnd = Name; |
828 | 167 | unsigned i; |
829 | 167 | if (StringRef(DigitStart, DigitEnd - DigitStart + 1) |
830 | 167 | .getAsInteger(10, i)) |
831 | 0 | return false; |
832 | | |
833 | | // Check if matching constraint is out of bounds. |
834 | 167 | if (i >= OutputConstraints.size()) return false1 ; |
835 | | |
836 | | // A number must refer to an output only operand. |
837 | 166 | if (OutputConstraints[i].isReadWrite()) |
838 | 1 | return false; |
839 | | |
840 | | // If the constraint is already tied, it must be tied to the |
841 | | // same operand referenced to by the number. |
842 | 165 | if (Info.hasTiedOperand() && Info.getTiedOperand() != i1 ) |
843 | 1 | return false; |
844 | | |
845 | | // The constraint should have the same info as the respective |
846 | | // output constraint. |
847 | 164 | Info.setTiedOperand(i, OutputConstraints[i]); |
848 | 6.67k | } else if (!validateAsmConstraint(Name, Info)) { |
849 | | // FIXME: This error return is in place temporarily so we can |
850 | | // add more constraints as we hit it. Eventually, an unknown |
851 | | // constraint should just be treated as 'g'. |
852 | 15 | return false; |
853 | 15 | } |
854 | 6.82k | break; |
855 | 6.82k | case '[': { |
856 | 46 | unsigned Index = 0; |
857 | 46 | if (!resolveSymbolicName(Name, OutputConstraints, Index)) |
858 | 3 | return false; |
859 | | |
860 | | // If the constraint is already tied, it must be tied to the |
861 | | // same operand referenced to by the number. |
862 | 43 | if (Info.hasTiedOperand() && Info.getTiedOperand() != Index1 ) |
863 | 1 | return false; |
864 | | |
865 | | // A number must refer to an output only operand. |
866 | 42 | if (OutputConstraints[Index].isReadWrite()) |
867 | 1 | return false; |
868 | | |
869 | 41 | Info.setTiedOperand(Index, OutputConstraints[Index]); |
870 | 41 | break; |
871 | 42 | } |
872 | 0 | case '%': // commutative |
873 | | // FIXME: Fail if % is used with the last operand. |
874 | 0 | break; |
875 | 365 | case 'i': // immediate integer. |
876 | 365 | break; |
877 | 81 | case 'n': // immediate integer with a known value. |
878 | 81 | Info.setRequiresImmediate(); |
879 | 81 | break; |
880 | 79 | case 'I': // Various constant constraints with target-specific meanings. |
881 | 144 | case 'J': |
882 | 190 | case 'K': |
883 | 240 | case 'L': |
884 | 260 | case 'M': |
885 | 293 | case 'N': |
886 | 303 | case 'O': |
887 | 303 | case 'P': |
888 | 303 | if (!validateAsmConstraint(Name, Info)) |
889 | 16 | return false; |
890 | 287 | break; |
891 | 3.82k | case 'r': // general register. |
892 | 3.82k | Info.setAllowsRegister(); |
893 | 3.82k | break; |
894 | 446 | case 'm': // memory operand. |
895 | 446 | case 'o': // offsettable memory operand. |
896 | 446 | case 'V': // non-offsettable memory operand. |
897 | 534 | case '<': // autodecrement memory operand. |
898 | 622 | case '>': // autoincrement memory operand. |
899 | 622 | Info.setAllowsMemory(); |
900 | 622 | break; |
901 | 316 | case 'g': // general register, memory operand or immediate integer. |
902 | 581 | case 'X': // any operand. |
903 | 581 | Info.setAllowsRegister(); |
904 | 581 | Info.setAllowsMemory(); |
905 | 581 | break; |
906 | 44 | case 'E': // immediate floating point. |
907 | 88 | case 'F': // immediate floating point. |
908 | 139 | case 'p': // address operand. |
909 | 139 | break; |
910 | 683 | case ',': // multiple alternative constraint. Ignore comma. |
911 | 683 | break; |
912 | 3 | case '#': // Ignore as constraint. |
913 | 7 | while (Name[1] && Name[1] != ','6 ) |
914 | 4 | Name++; |
915 | 3 | break; |
916 | 0 | case '?': // Disparage slightly code. |
917 | 0 | case '!': // Disparage severely. |
918 | 2 | case '*': // Ignore for choosing register preferences. |
919 | 2 | break; // Pass them. |
920 | 13.4k | } |
921 | | |
922 | 13.4k | Name++; |
923 | 13.4k | } |
924 | | |
925 | 11.8k | return true; |
926 | 11.9k | } |
927 | | |
928 | 289k | void TargetInfo::CheckFixedPointBits() const { |
929 | | // Check that the number of fractional and integral bits (and maybe sign) can |
930 | | // fit into the bits given for a fixed point type. |
931 | 289k | assert(ShortAccumScale + getShortAccumIBits() + 1 <= ShortAccumWidth); |
932 | 289k | assert(AccumScale + getAccumIBits() + 1 <= AccumWidth); |
933 | 289k | assert(LongAccumScale + getLongAccumIBits() + 1 <= LongAccumWidth); |
934 | 289k | assert(getUnsignedShortAccumScale() + getUnsignedShortAccumIBits() <= |
935 | 289k | ShortAccumWidth); |
936 | 289k | assert(getUnsignedAccumScale() + getUnsignedAccumIBits() <= AccumWidth); |
937 | 289k | assert(getUnsignedLongAccumScale() + getUnsignedLongAccumIBits() <= |
938 | 289k | LongAccumWidth); |
939 | | |
940 | 289k | assert(getShortFractScale() + 1 <= ShortFractWidth); |
941 | 289k | assert(getFractScale() + 1 <= FractWidth); |
942 | 289k | assert(getLongFractScale() + 1 <= LongFractWidth); |
943 | 289k | assert(getUnsignedShortFractScale() <= ShortFractWidth); |
944 | 289k | assert(getUnsignedFractScale() <= FractWidth); |
945 | 289k | assert(getUnsignedLongFractScale() <= LongFractWidth); |
946 | | |
947 | | // Each unsigned fract type has either the same number of fractional bits |
948 | | // as, or one more fractional bit than, its corresponding signed fract type. |
949 | 289k | assert(getShortFractScale() == getUnsignedShortFractScale() || |
950 | 289k | getShortFractScale() == getUnsignedShortFractScale() - 1); |
951 | 289k | assert(getFractScale() == getUnsignedFractScale() || |
952 | 289k | getFractScale() == getUnsignedFractScale() - 1); |
953 | 289k | assert(getLongFractScale() == getUnsignedLongFractScale() || |
954 | 289k | getLongFractScale() == getUnsignedLongFractScale() - 1); |
955 | | |
956 | | // When arranged in order of increasing rank (see 6.3.1.3a), the number of |
957 | | // fractional bits is nondecreasing for each of the following sets of |
958 | | // fixed-point types: |
959 | | // - signed fract types |
960 | | // - unsigned fract types |
961 | | // - signed accum types |
962 | | // - unsigned accum types. |
963 | 289k | assert(getLongFractScale() >= getFractScale() && |
964 | 289k | getFractScale() >= getShortFractScale()); |
965 | 289k | assert(getUnsignedLongFractScale() >= getUnsignedFractScale() && |
966 | 289k | getUnsignedFractScale() >= getUnsignedShortFractScale()); |
967 | 289k | assert(LongAccumScale >= AccumScale && AccumScale >= ShortAccumScale); |
968 | 289k | assert(getUnsignedLongAccumScale() >= getUnsignedAccumScale() && |
969 | 289k | getUnsignedAccumScale() >= getUnsignedShortAccumScale()); |
970 | | |
971 | | // When arranged in order of increasing rank (see 6.3.1.3a), the number of |
972 | | // integral bits is nondecreasing for each of the following sets of |
973 | | // fixed-point types: |
974 | | // - signed accum types |
975 | | // - unsigned accum types |
976 | 289k | assert(getLongAccumIBits() >= getAccumIBits() && |
977 | 289k | getAccumIBits() >= getShortAccumIBits()); |
978 | 289k | assert(getUnsignedLongAccumIBits() >= getUnsignedAccumIBits() && |
979 | 289k | getUnsignedAccumIBits() >= getUnsignedShortAccumIBits()); |
980 | | |
981 | | // Each signed accum type has at least as many integral bits as its |
982 | | // corresponding unsigned accum type. |
983 | 289k | assert(getShortAccumIBits() >= getUnsignedShortAccumIBits()); |
984 | 289k | assert(getAccumIBits() >= getUnsignedAccumIBits()); |
985 | 289k | assert(getLongAccumIBits() >= getUnsignedLongAccumIBits()); |
986 | 289k | } |
987 | | |
988 | 83 | void TargetInfo::copyAuxTarget(const TargetInfo *Aux) { |
989 | 83 | auto *Target = static_cast<TransferrableTargetInfo*>(this); |
990 | 83 | auto *Src = static_cast<const TransferrableTargetInfo*>(Aux); |
991 | 83 | *Target = *Src; |
992 | 83 | } |