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