106f32e7eSjoerg //===--- TargetInfo.cpp - Information about Target machine ----------------===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg //
906f32e7eSjoerg // This file implements the TargetInfo and TargetInfoImpl interfaces.
1006f32e7eSjoerg //
1106f32e7eSjoerg //===----------------------------------------------------------------------===//
1206f32e7eSjoerg
1306f32e7eSjoerg #include "clang/Basic/TargetInfo.h"
1406f32e7eSjoerg #include "clang/Basic/AddressSpaces.h"
1506f32e7eSjoerg #include "clang/Basic/CharInfo.h"
1606f32e7eSjoerg #include "clang/Basic/Diagnostic.h"
1706f32e7eSjoerg #include "clang/Basic/LangOptions.h"
1806f32e7eSjoerg #include "llvm/ADT/APFloat.h"
1906f32e7eSjoerg #include "llvm/ADT/STLExtras.h"
2006f32e7eSjoerg #include "llvm/Support/ErrorHandling.h"
2106f32e7eSjoerg #include "llvm/Support/TargetParser.h"
2206f32e7eSjoerg #include <cstdlib>
2306f32e7eSjoerg using namespace clang;
2406f32e7eSjoerg
2506f32e7eSjoerg static const LangASMap DefaultAddrSpaceMap = {0};
2606f32e7eSjoerg
2706f32e7eSjoerg // TargetInfo Constructor.
TargetInfo(const llvm::Triple & T)2806f32e7eSjoerg TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
2906f32e7eSjoerg // Set defaults. Defaults are set for a 32-bit RISC platform, like PPC or
3006f32e7eSjoerg // SPARC. These should be overridden by concrete targets as needed.
3106f32e7eSjoerg BigEndian = !T.isLittleEndian();
3206f32e7eSjoerg TLSSupported = true;
3306f32e7eSjoerg VLASupported = true;
3406f32e7eSjoerg NoAsmVariants = false;
3506f32e7eSjoerg HasLegalHalfType = false;
3606f32e7eSjoerg HasFloat128 = false;
3706f32e7eSjoerg HasFloat16 = false;
38*13fbcb42Sjoerg HasBFloat16 = false;
39*13fbcb42Sjoerg HasStrictFP = false;
4006f32e7eSjoerg PointerWidth = PointerAlign = 32;
4106f32e7eSjoerg BoolWidth = BoolAlign = 8;
4206f32e7eSjoerg IntWidth = IntAlign = 32;
4306f32e7eSjoerg LongWidth = LongAlign = 32;
4406f32e7eSjoerg LongLongWidth = LongLongAlign = 64;
4506f32e7eSjoerg
4606f32e7eSjoerg // Fixed point default bit widths
4706f32e7eSjoerg ShortAccumWidth = ShortAccumAlign = 16;
4806f32e7eSjoerg AccumWidth = AccumAlign = 32;
4906f32e7eSjoerg LongAccumWidth = LongAccumAlign = 64;
5006f32e7eSjoerg ShortFractWidth = ShortFractAlign = 8;
5106f32e7eSjoerg FractWidth = FractAlign = 16;
5206f32e7eSjoerg LongFractWidth = LongFractAlign = 32;
5306f32e7eSjoerg
5406f32e7eSjoerg // Fixed point default integral and fractional bit sizes
5506f32e7eSjoerg // We give the _Accum 1 fewer fractional bits than their corresponding _Fract
5606f32e7eSjoerg // types by default to have the same number of fractional bits between _Accum
5706f32e7eSjoerg // and _Fract types.
5806f32e7eSjoerg PaddingOnUnsignedFixedPoint = false;
5906f32e7eSjoerg ShortAccumScale = 7;
6006f32e7eSjoerg AccumScale = 15;
6106f32e7eSjoerg LongAccumScale = 31;
6206f32e7eSjoerg
6306f32e7eSjoerg SuitableAlign = 64;
6406f32e7eSjoerg DefaultAlignForAttributeAligned = 128;
6506f32e7eSjoerg MinGlobalAlign = 0;
6606f32e7eSjoerg // From the glibc documentation, on GNU systems, malloc guarantees 16-byte
6706f32e7eSjoerg // alignment on 64-bit systems and 8-byte alignment on 32-bit systems. See
6806f32e7eSjoerg // https://www.gnu.org/software/libc/manual/html_node/Malloc-Examples.html.
69*13fbcb42Sjoerg // This alignment guarantee also applies to Windows and Android. On Darwin,
70*13fbcb42Sjoerg // the alignment is 16 bytes on both 64-bit and 32-bit systems.
7106f32e7eSjoerg if (T.isGNUEnvironment() || T.isWindowsMSVCEnvironment() || T.isAndroid())
7206f32e7eSjoerg NewAlign = Triple.isArch64Bit() ? 128 : Triple.isArch32Bit() ? 64 : 0;
73*13fbcb42Sjoerg else if (T.isOSDarwin())
74*13fbcb42Sjoerg NewAlign = 128;
7506f32e7eSjoerg else
7606f32e7eSjoerg NewAlign = 0; // Infer from basic type alignment.
7706f32e7eSjoerg HalfWidth = 16;
7806f32e7eSjoerg HalfAlign = 16;
7906f32e7eSjoerg FloatWidth = 32;
8006f32e7eSjoerg FloatAlign = 32;
8106f32e7eSjoerg DoubleWidth = 64;
8206f32e7eSjoerg DoubleAlign = 64;
8306f32e7eSjoerg LongDoubleWidth = 64;
8406f32e7eSjoerg LongDoubleAlign = 64;
8506f32e7eSjoerg Float128Align = 128;
8606f32e7eSjoerg LargeArrayMinWidth = 0;
8706f32e7eSjoerg LargeArrayAlign = 0;
8806f32e7eSjoerg MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0;
8906f32e7eSjoerg MaxVectorAlign = 0;
9006f32e7eSjoerg MaxTLSAlign = 0;
9106f32e7eSjoerg SimdDefaultAlign = 0;
9206f32e7eSjoerg SizeType = UnsignedLong;
9306f32e7eSjoerg PtrDiffType = SignedLong;
9406f32e7eSjoerg IntMaxType = SignedLongLong;
9506f32e7eSjoerg IntPtrType = SignedLong;
9606f32e7eSjoerg WCharType = SignedInt;
9706f32e7eSjoerg WIntType = SignedInt;
9806f32e7eSjoerg Char16Type = UnsignedShort;
9906f32e7eSjoerg Char32Type = UnsignedInt;
10006f32e7eSjoerg Int64Type = SignedLongLong;
101*13fbcb42Sjoerg Int16Type = SignedShort;
10206f32e7eSjoerg SigAtomicType = SignedInt;
10306f32e7eSjoerg ProcessIDType = SignedInt;
10406f32e7eSjoerg UseSignedCharForObjCBool = true;
10506f32e7eSjoerg UseBitFieldTypeAlignment = true;
10606f32e7eSjoerg UseZeroLengthBitfieldAlignment = false;
107*13fbcb42Sjoerg UseLeadingZeroLengthBitfield = true;
10806f32e7eSjoerg UseExplicitBitFieldAlignment = true;
10906f32e7eSjoerg ZeroLengthBitfieldBoundary = 0;
110*13fbcb42Sjoerg MaxAlignedAttribute = 0;
11106f32e7eSjoerg HalfFormat = &llvm::APFloat::IEEEhalf();
11206f32e7eSjoerg FloatFormat = &llvm::APFloat::IEEEsingle();
11306f32e7eSjoerg DoubleFormat = &llvm::APFloat::IEEEdouble();
11406f32e7eSjoerg LongDoubleFormat = &llvm::APFloat::IEEEdouble();
11506f32e7eSjoerg Float128Format = &llvm::APFloat::IEEEquad();
11606f32e7eSjoerg MCountName = "mcount";
117*13fbcb42Sjoerg UserLabelPrefix = "_";
11806f32e7eSjoerg RegParmMax = 0;
11906f32e7eSjoerg SSERegParmMax = 0;
12006f32e7eSjoerg HasAlignMac68kSupport = false;
12106f32e7eSjoerg HasBuiltinMSVaList = false;
12206f32e7eSjoerg IsRenderScriptTarget = false;
12306f32e7eSjoerg HasAArch64SVETypes = false;
124*13fbcb42Sjoerg HasRISCVVTypes = false;
125*13fbcb42Sjoerg AllowAMDGPUUnsafeFPAtomics = false;
126*13fbcb42Sjoerg ARMCDECoprocMask = 0;
12706f32e7eSjoerg
12806f32e7eSjoerg // Default to no types using fpret.
12906f32e7eSjoerg RealTypeUsesObjCFPRet = 0;
13006f32e7eSjoerg
13106f32e7eSjoerg // Default to not using fp2ret for __Complex long double
13206f32e7eSjoerg ComplexLongDoubleUsesFP2Ret = false;
13306f32e7eSjoerg
13406f32e7eSjoerg // Set the C++ ABI based on the triple.
13506f32e7eSjoerg TheCXXABI.set(Triple.isKnownWindowsMSVCEnvironment()
13606f32e7eSjoerg ? TargetCXXABI::Microsoft
13706f32e7eSjoerg : TargetCXXABI::GenericItanium);
13806f32e7eSjoerg
13906f32e7eSjoerg // Default to an empty address space map.
14006f32e7eSjoerg AddrSpaceMap = &DefaultAddrSpaceMap;
14106f32e7eSjoerg UseAddrSpaceMapMangling = false;
14206f32e7eSjoerg
14306f32e7eSjoerg // Default to an unknown platform name.
14406f32e7eSjoerg PlatformName = "unknown";
14506f32e7eSjoerg PlatformMinVersion = VersionTuple();
146*13fbcb42Sjoerg
147*13fbcb42Sjoerg MaxOpenCLWorkGroupSize = 1024;
14806f32e7eSjoerg }
14906f32e7eSjoerg
15006f32e7eSjoerg // Out of line virtual dtor for TargetInfo.
~TargetInfo()15106f32e7eSjoerg TargetInfo::~TargetInfo() {}
15206f32e7eSjoerg
resetDataLayout(StringRef DL,const char * ULP)153*13fbcb42Sjoerg void TargetInfo::resetDataLayout(StringRef DL, const char *ULP) {
154*13fbcb42Sjoerg DataLayoutString = DL.str();
155*13fbcb42Sjoerg UserLabelPrefix = ULP;
15606f32e7eSjoerg }
15706f32e7eSjoerg
15806f32e7eSjoerg bool
checkCFProtectionBranchSupported(DiagnosticsEngine & Diags) const15906f32e7eSjoerg TargetInfo::checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const {
16006f32e7eSjoerg Diags.Report(diag::err_opt_not_valid_on_target) << "cf-protection=branch";
16106f32e7eSjoerg return false;
16206f32e7eSjoerg }
16306f32e7eSjoerg
16406f32e7eSjoerg bool
checkCFProtectionReturnSupported(DiagnosticsEngine & Diags) const16506f32e7eSjoerg TargetInfo::checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const {
16606f32e7eSjoerg Diags.Report(diag::err_opt_not_valid_on_target) << "cf-protection=return";
16706f32e7eSjoerg return false;
16806f32e7eSjoerg }
16906f32e7eSjoerg
17006f32e7eSjoerg /// getTypeName - Return the user string for the specified integer type enum.
17106f32e7eSjoerg /// For example, SignedShort -> "short".
getTypeName(IntType T)17206f32e7eSjoerg const char *TargetInfo::getTypeName(IntType T) {
17306f32e7eSjoerg switch (T) {
17406f32e7eSjoerg default: llvm_unreachable("not an integer!");
17506f32e7eSjoerg case SignedChar: return "signed char";
17606f32e7eSjoerg case UnsignedChar: return "unsigned char";
17706f32e7eSjoerg case SignedShort: return "short";
17806f32e7eSjoerg case UnsignedShort: return "unsigned short";
17906f32e7eSjoerg case SignedInt: return "int";
18006f32e7eSjoerg case UnsignedInt: return "unsigned int";
18106f32e7eSjoerg case SignedLong: return "long int";
18206f32e7eSjoerg case UnsignedLong: return "long unsigned int";
18306f32e7eSjoerg case SignedLongLong: return "long long int";
18406f32e7eSjoerg case UnsignedLongLong: return "long long unsigned int";
18506f32e7eSjoerg }
18606f32e7eSjoerg }
18706f32e7eSjoerg
18806f32e7eSjoerg /// getTypeConstantSuffix - Return the constant suffix for the specified
18906f32e7eSjoerg /// integer type enum. For example, SignedLong -> "L".
getTypeConstantSuffix(IntType T) const19006f32e7eSjoerg const char *TargetInfo::getTypeConstantSuffix(IntType T) const {
19106f32e7eSjoerg switch (T) {
19206f32e7eSjoerg default: llvm_unreachable("not an integer!");
19306f32e7eSjoerg case SignedChar:
19406f32e7eSjoerg case SignedShort:
19506f32e7eSjoerg case SignedInt: return "";
19606f32e7eSjoerg case SignedLong: return "L";
19706f32e7eSjoerg case SignedLongLong: return "LL";
19806f32e7eSjoerg case UnsignedChar:
19906f32e7eSjoerg if (getCharWidth() < getIntWidth())
20006f32e7eSjoerg return "";
20106f32e7eSjoerg LLVM_FALLTHROUGH;
20206f32e7eSjoerg case UnsignedShort:
20306f32e7eSjoerg if (getShortWidth() < getIntWidth())
20406f32e7eSjoerg return "";
20506f32e7eSjoerg LLVM_FALLTHROUGH;
20606f32e7eSjoerg case UnsignedInt: return "U";
20706f32e7eSjoerg case UnsignedLong: return "UL";
20806f32e7eSjoerg case UnsignedLongLong: return "ULL";
20906f32e7eSjoerg }
21006f32e7eSjoerg }
21106f32e7eSjoerg
21206f32e7eSjoerg /// getTypeFormatModifier - Return the printf format modifier for the
21306f32e7eSjoerg /// specified integer type enum. For example, SignedLong -> "l".
21406f32e7eSjoerg
getTypeFormatModifier(IntType T)21506f32e7eSjoerg const char *TargetInfo::getTypeFormatModifier(IntType T) {
21606f32e7eSjoerg switch (T) {
21706f32e7eSjoerg default: llvm_unreachable("not an integer!");
21806f32e7eSjoerg case SignedChar:
21906f32e7eSjoerg case UnsignedChar: return "hh";
22006f32e7eSjoerg case SignedShort:
22106f32e7eSjoerg case UnsignedShort: return "h";
22206f32e7eSjoerg case SignedInt:
22306f32e7eSjoerg case UnsignedInt: return "";
22406f32e7eSjoerg case SignedLong:
22506f32e7eSjoerg case UnsignedLong: return "l";
22606f32e7eSjoerg case SignedLongLong:
22706f32e7eSjoerg case UnsignedLongLong: return "ll";
22806f32e7eSjoerg }
22906f32e7eSjoerg }
23006f32e7eSjoerg
23106f32e7eSjoerg /// getTypeWidth - Return the width (in bits) of the specified integer type
23206f32e7eSjoerg /// enum. For example, SignedInt -> getIntWidth().
getTypeWidth(IntType T) const23306f32e7eSjoerg unsigned TargetInfo::getTypeWidth(IntType T) const {
23406f32e7eSjoerg switch (T) {
23506f32e7eSjoerg default: llvm_unreachable("not an integer!");
23606f32e7eSjoerg case SignedChar:
23706f32e7eSjoerg case UnsignedChar: return getCharWidth();
23806f32e7eSjoerg case SignedShort:
23906f32e7eSjoerg case UnsignedShort: return getShortWidth();
24006f32e7eSjoerg case SignedInt:
24106f32e7eSjoerg case UnsignedInt: return getIntWidth();
24206f32e7eSjoerg case SignedLong:
24306f32e7eSjoerg case UnsignedLong: return getLongWidth();
24406f32e7eSjoerg case SignedLongLong:
24506f32e7eSjoerg case UnsignedLongLong: return getLongLongWidth();
24606f32e7eSjoerg };
24706f32e7eSjoerg }
24806f32e7eSjoerg
getIntTypeByWidth(unsigned BitWidth,bool IsSigned) const24906f32e7eSjoerg TargetInfo::IntType TargetInfo::getIntTypeByWidth(
25006f32e7eSjoerg unsigned BitWidth, bool IsSigned) const {
25106f32e7eSjoerg if (getCharWidth() == BitWidth)
25206f32e7eSjoerg return IsSigned ? SignedChar : UnsignedChar;
25306f32e7eSjoerg if (getShortWidth() == BitWidth)
25406f32e7eSjoerg return IsSigned ? SignedShort : UnsignedShort;
25506f32e7eSjoerg if (getIntWidth() == BitWidth)
25606f32e7eSjoerg return IsSigned ? SignedInt : UnsignedInt;
25706f32e7eSjoerg if (getLongWidth() == BitWidth)
25806f32e7eSjoerg return IsSigned ? SignedLong : UnsignedLong;
25906f32e7eSjoerg if (getLongLongWidth() == BitWidth)
26006f32e7eSjoerg return IsSigned ? SignedLongLong : UnsignedLongLong;
26106f32e7eSjoerg return NoInt;
26206f32e7eSjoerg }
26306f32e7eSjoerg
getLeastIntTypeByWidth(unsigned BitWidth,bool IsSigned) const26406f32e7eSjoerg TargetInfo::IntType TargetInfo::getLeastIntTypeByWidth(unsigned BitWidth,
26506f32e7eSjoerg bool IsSigned) const {
26606f32e7eSjoerg if (getCharWidth() >= BitWidth)
26706f32e7eSjoerg return IsSigned ? SignedChar : UnsignedChar;
26806f32e7eSjoerg if (getShortWidth() >= BitWidth)
26906f32e7eSjoerg return IsSigned ? SignedShort : UnsignedShort;
27006f32e7eSjoerg if (getIntWidth() >= BitWidth)
27106f32e7eSjoerg return IsSigned ? SignedInt : UnsignedInt;
27206f32e7eSjoerg if (getLongWidth() >= BitWidth)
27306f32e7eSjoerg return IsSigned ? SignedLong : UnsignedLong;
27406f32e7eSjoerg if (getLongLongWidth() >= BitWidth)
27506f32e7eSjoerg return IsSigned ? SignedLongLong : UnsignedLongLong;
27606f32e7eSjoerg return NoInt;
27706f32e7eSjoerg }
27806f32e7eSjoerg
getRealTypeByWidth(unsigned BitWidth,bool ExplicitIEEE) const279*13fbcb42Sjoerg TargetInfo::RealType TargetInfo::getRealTypeByWidth(unsigned BitWidth,
280*13fbcb42Sjoerg bool ExplicitIEEE) const {
28106f32e7eSjoerg if (getFloatWidth() == BitWidth)
28206f32e7eSjoerg return Float;
28306f32e7eSjoerg if (getDoubleWidth() == BitWidth)
28406f32e7eSjoerg return Double;
28506f32e7eSjoerg
28606f32e7eSjoerg switch (BitWidth) {
28706f32e7eSjoerg case 96:
28806f32e7eSjoerg if (&getLongDoubleFormat() == &llvm::APFloat::x87DoubleExtended())
28906f32e7eSjoerg return LongDouble;
29006f32e7eSjoerg break;
29106f32e7eSjoerg case 128:
292*13fbcb42Sjoerg // The caller explicitly asked for an IEEE compliant type but we still
293*13fbcb42Sjoerg // have to check if the target supports it.
294*13fbcb42Sjoerg if (ExplicitIEEE)
295*13fbcb42Sjoerg return hasFloat128Type() ? Float128 : NoFloat;
29606f32e7eSjoerg if (&getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble() ||
29706f32e7eSjoerg &getLongDoubleFormat() == &llvm::APFloat::IEEEquad())
29806f32e7eSjoerg return LongDouble;
29906f32e7eSjoerg if (hasFloat128Type())
30006f32e7eSjoerg return Float128;
30106f32e7eSjoerg break;
30206f32e7eSjoerg }
30306f32e7eSjoerg
30406f32e7eSjoerg return NoFloat;
30506f32e7eSjoerg }
30606f32e7eSjoerg
30706f32e7eSjoerg /// getTypeAlign - Return the alignment (in bits) of the specified integer type
30806f32e7eSjoerg /// enum. For example, SignedInt -> getIntAlign().
getTypeAlign(IntType T) const30906f32e7eSjoerg unsigned TargetInfo::getTypeAlign(IntType T) const {
31006f32e7eSjoerg switch (T) {
31106f32e7eSjoerg default: llvm_unreachable("not an integer!");
31206f32e7eSjoerg case SignedChar:
31306f32e7eSjoerg case UnsignedChar: return getCharAlign();
31406f32e7eSjoerg case SignedShort:
31506f32e7eSjoerg case UnsignedShort: return getShortAlign();
31606f32e7eSjoerg case SignedInt:
31706f32e7eSjoerg case UnsignedInt: return getIntAlign();
31806f32e7eSjoerg case SignedLong:
31906f32e7eSjoerg case UnsignedLong: return getLongAlign();
32006f32e7eSjoerg case SignedLongLong:
32106f32e7eSjoerg case UnsignedLongLong: return getLongLongAlign();
32206f32e7eSjoerg };
32306f32e7eSjoerg }
32406f32e7eSjoerg
32506f32e7eSjoerg /// isTypeSigned - Return whether an integer types is signed. Returns true if
32606f32e7eSjoerg /// the type is signed; false otherwise.
isTypeSigned(IntType T)32706f32e7eSjoerg bool TargetInfo::isTypeSigned(IntType T) {
32806f32e7eSjoerg switch (T) {
32906f32e7eSjoerg default: llvm_unreachable("not an integer!");
33006f32e7eSjoerg case SignedChar:
33106f32e7eSjoerg case SignedShort:
33206f32e7eSjoerg case SignedInt:
33306f32e7eSjoerg case SignedLong:
33406f32e7eSjoerg case SignedLongLong:
33506f32e7eSjoerg return true;
33606f32e7eSjoerg case UnsignedChar:
33706f32e7eSjoerg case UnsignedShort:
33806f32e7eSjoerg case UnsignedInt:
33906f32e7eSjoerg case UnsignedLong:
34006f32e7eSjoerg case UnsignedLongLong:
34106f32e7eSjoerg return false;
34206f32e7eSjoerg };
34306f32e7eSjoerg }
34406f32e7eSjoerg
34506f32e7eSjoerg /// adjust - Set forced language options.
34606f32e7eSjoerg /// Apply changes to the target information with respect to certain
34706f32e7eSjoerg /// language options which change the target configuration and adjust
34806f32e7eSjoerg /// the language based on the target options where applicable.
adjust(LangOptions & Opts)34906f32e7eSjoerg void TargetInfo::adjust(LangOptions &Opts) {
35006f32e7eSjoerg if (Opts.NoBitFieldTypeAlign)
35106f32e7eSjoerg UseBitFieldTypeAlignment = false;
35206f32e7eSjoerg
35306f32e7eSjoerg switch (Opts.WCharSize) {
35406f32e7eSjoerg default: llvm_unreachable("invalid wchar_t width");
35506f32e7eSjoerg case 0: break;
35606f32e7eSjoerg case 1: WCharType = Opts.WCharIsSigned ? SignedChar : UnsignedChar; break;
35706f32e7eSjoerg case 2: WCharType = Opts.WCharIsSigned ? SignedShort : UnsignedShort; break;
35806f32e7eSjoerg case 4: WCharType = Opts.WCharIsSigned ? SignedInt : UnsignedInt; break;
35906f32e7eSjoerg }
36006f32e7eSjoerg
36106f32e7eSjoerg if (Opts.AlignDouble) {
36206f32e7eSjoerg DoubleAlign = LongLongAlign = 64;
36306f32e7eSjoerg LongDoubleAlign = 64;
36406f32e7eSjoerg }
36506f32e7eSjoerg
36606f32e7eSjoerg if (Opts.OpenCL) {
36706f32e7eSjoerg // OpenCL C requires specific widths for types, irrespective of
36806f32e7eSjoerg // what these normally are for the target.
36906f32e7eSjoerg // We also define long long and long double here, although the
37006f32e7eSjoerg // OpenCL standard only mentions these as "reserved".
37106f32e7eSjoerg IntWidth = IntAlign = 32;
37206f32e7eSjoerg LongWidth = LongAlign = 64;
37306f32e7eSjoerg LongLongWidth = LongLongAlign = 128;
37406f32e7eSjoerg HalfWidth = HalfAlign = 16;
37506f32e7eSjoerg FloatWidth = FloatAlign = 32;
37606f32e7eSjoerg
37706f32e7eSjoerg // Embedded 32-bit targets (OpenCL EP) might have double C type
37806f32e7eSjoerg // defined as float. Let's not override this as it might lead
37906f32e7eSjoerg // to generating illegal code that uses 64bit doubles.
38006f32e7eSjoerg if (DoubleWidth != FloatWidth) {
38106f32e7eSjoerg DoubleWidth = DoubleAlign = 64;
38206f32e7eSjoerg DoubleFormat = &llvm::APFloat::IEEEdouble();
38306f32e7eSjoerg }
38406f32e7eSjoerg LongDoubleWidth = LongDoubleAlign = 128;
38506f32e7eSjoerg
38606f32e7eSjoerg unsigned MaxPointerWidth = getMaxPointerWidth();
38706f32e7eSjoerg assert(MaxPointerWidth == 32 || MaxPointerWidth == 64);
38806f32e7eSjoerg bool Is32BitArch = MaxPointerWidth == 32;
38906f32e7eSjoerg SizeType = Is32BitArch ? UnsignedInt : UnsignedLong;
39006f32e7eSjoerg PtrDiffType = Is32BitArch ? SignedInt : SignedLong;
39106f32e7eSjoerg IntPtrType = Is32BitArch ? SignedInt : SignedLong;
39206f32e7eSjoerg
39306f32e7eSjoerg IntMaxType = SignedLongLong;
39406f32e7eSjoerg Int64Type = SignedLong;
39506f32e7eSjoerg
39606f32e7eSjoerg HalfFormat = &llvm::APFloat::IEEEhalf();
39706f32e7eSjoerg FloatFormat = &llvm::APFloat::IEEEsingle();
39806f32e7eSjoerg LongDoubleFormat = &llvm::APFloat::IEEEquad();
39906f32e7eSjoerg }
40006f32e7eSjoerg
401*13fbcb42Sjoerg if (Opts.DoubleSize) {
402*13fbcb42Sjoerg if (Opts.DoubleSize == 32) {
403*13fbcb42Sjoerg DoubleWidth = 32;
404*13fbcb42Sjoerg LongDoubleWidth = 32;
405*13fbcb42Sjoerg DoubleFormat = &llvm::APFloat::IEEEsingle();
406*13fbcb42Sjoerg LongDoubleFormat = &llvm::APFloat::IEEEsingle();
407*13fbcb42Sjoerg } else if (Opts.DoubleSize == 64) {
408*13fbcb42Sjoerg DoubleWidth = 64;
409*13fbcb42Sjoerg LongDoubleWidth = 64;
410*13fbcb42Sjoerg DoubleFormat = &llvm::APFloat::IEEEdouble();
411*13fbcb42Sjoerg LongDoubleFormat = &llvm::APFloat::IEEEdouble();
412*13fbcb42Sjoerg }
413*13fbcb42Sjoerg }
414*13fbcb42Sjoerg
41506f32e7eSjoerg if (Opts.LongDoubleSize) {
41606f32e7eSjoerg if (Opts.LongDoubleSize == DoubleWidth) {
41706f32e7eSjoerg LongDoubleWidth = DoubleWidth;
41806f32e7eSjoerg LongDoubleAlign = DoubleAlign;
41906f32e7eSjoerg LongDoubleFormat = DoubleFormat;
42006f32e7eSjoerg } else if (Opts.LongDoubleSize == 128) {
42106f32e7eSjoerg LongDoubleWidth = LongDoubleAlign = 128;
42206f32e7eSjoerg LongDoubleFormat = &llvm::APFloat::IEEEquad();
42306f32e7eSjoerg }
42406f32e7eSjoerg }
42506f32e7eSjoerg
42606f32e7eSjoerg if (Opts.NewAlignOverride)
42706f32e7eSjoerg NewAlign = Opts.NewAlignOverride * getCharWidth();
42806f32e7eSjoerg
42906f32e7eSjoerg // Each unsigned fixed point type has the same number of fractional bits as
43006f32e7eSjoerg // its corresponding signed type.
43106f32e7eSjoerg PaddingOnUnsignedFixedPoint |= Opts.PaddingOnUnsignedFixedPoint;
43206f32e7eSjoerg CheckFixedPointBits();
43306f32e7eSjoerg }
43406f32e7eSjoerg
initFeatureMap(llvm::StringMap<bool> & Features,DiagnosticsEngine & Diags,StringRef CPU,const std::vector<std::string> & FeatureVec) const43506f32e7eSjoerg bool TargetInfo::initFeatureMap(
43606f32e7eSjoerg llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
43706f32e7eSjoerg const std::vector<std::string> &FeatureVec) const {
43806f32e7eSjoerg for (const auto &F : FeatureVec) {
43906f32e7eSjoerg StringRef Name = F;
44006f32e7eSjoerg // Apply the feature via the target.
44106f32e7eSjoerg bool Enabled = Name[0] == '+';
44206f32e7eSjoerg setFeatureEnabled(Features, Name.substr(1), Enabled);
44306f32e7eSjoerg }
44406f32e7eSjoerg return true;
44506f32e7eSjoerg }
44606f32e7eSjoerg
44706f32e7eSjoerg TargetInfo::CallingConvKind
getCallingConvKind(bool ClangABICompat4) const44806f32e7eSjoerg TargetInfo::getCallingConvKind(bool ClangABICompat4) const {
44906f32e7eSjoerg if (getCXXABI() != TargetCXXABI::Microsoft &&
45006f32e7eSjoerg (ClangABICompat4 || getTriple().getOS() == llvm::Triple::PS4))
45106f32e7eSjoerg return CCK_ClangABI4OrPS4;
45206f32e7eSjoerg return CCK_Default;
45306f32e7eSjoerg }
45406f32e7eSjoerg
getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const45506f32e7eSjoerg LangAS TargetInfo::getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const {
45606f32e7eSjoerg switch (TK) {
45706f32e7eSjoerg case OCLTK_Image:
45806f32e7eSjoerg case OCLTK_Pipe:
45906f32e7eSjoerg return LangAS::opencl_global;
46006f32e7eSjoerg
46106f32e7eSjoerg case OCLTK_Sampler:
46206f32e7eSjoerg return LangAS::opencl_constant;
46306f32e7eSjoerg
46406f32e7eSjoerg default:
46506f32e7eSjoerg return LangAS::Default;
46606f32e7eSjoerg }
46706f32e7eSjoerg }
46806f32e7eSjoerg
46906f32e7eSjoerg //===----------------------------------------------------------------------===//
47006f32e7eSjoerg
47106f32e7eSjoerg
removeGCCRegisterPrefix(StringRef Name)47206f32e7eSjoerg static StringRef removeGCCRegisterPrefix(StringRef Name) {
47306f32e7eSjoerg if (Name[0] == '%' || Name[0] == '#')
47406f32e7eSjoerg Name = Name.substr(1);
47506f32e7eSjoerg
47606f32e7eSjoerg return Name;
47706f32e7eSjoerg }
47806f32e7eSjoerg
47906f32e7eSjoerg /// isValidClobber - Returns whether the passed in string is
48006f32e7eSjoerg /// a valid clobber in an inline asm statement. This is used by
48106f32e7eSjoerg /// Sema.
isValidClobber(StringRef Name) const48206f32e7eSjoerg bool TargetInfo::isValidClobber(StringRef Name) const {
483*13fbcb42Sjoerg return (isValidGCCRegisterName(Name) || Name == "memory" || Name == "cc" ||
484*13fbcb42Sjoerg Name == "unwind");
48506f32e7eSjoerg }
48606f32e7eSjoerg
48706f32e7eSjoerg /// isValidGCCRegisterName - Returns whether the passed in string
48806f32e7eSjoerg /// is a valid register name according to GCC. This is used by Sema for
48906f32e7eSjoerg /// inline asm statements.
isValidGCCRegisterName(StringRef Name) const49006f32e7eSjoerg bool TargetInfo::isValidGCCRegisterName(StringRef Name) const {
49106f32e7eSjoerg if (Name.empty())
49206f32e7eSjoerg return false;
49306f32e7eSjoerg
49406f32e7eSjoerg // Get rid of any register prefix.
49506f32e7eSjoerg Name = removeGCCRegisterPrefix(Name);
49606f32e7eSjoerg if (Name.empty())
49706f32e7eSjoerg return false;
49806f32e7eSjoerg
49906f32e7eSjoerg ArrayRef<const char *> Names = getGCCRegNames();
50006f32e7eSjoerg
50106f32e7eSjoerg // If we have a number it maps to an entry in the register name array.
50206f32e7eSjoerg if (isDigit(Name[0])) {
50306f32e7eSjoerg unsigned n;
50406f32e7eSjoerg if (!Name.getAsInteger(0, n))
50506f32e7eSjoerg return n < Names.size();
50606f32e7eSjoerg }
50706f32e7eSjoerg
50806f32e7eSjoerg // Check register names.
50906f32e7eSjoerg if (llvm::is_contained(Names, Name))
51006f32e7eSjoerg return true;
51106f32e7eSjoerg
51206f32e7eSjoerg // Check any additional names that we have.
51306f32e7eSjoerg for (const AddlRegName &ARN : getGCCAddlRegNames())
51406f32e7eSjoerg for (const char *AN : ARN.Names) {
51506f32e7eSjoerg if (!AN)
51606f32e7eSjoerg break;
51706f32e7eSjoerg // Make sure the register that the additional name is for is within
51806f32e7eSjoerg // the bounds of the register names from above.
51906f32e7eSjoerg if (AN == Name && ARN.RegNum < Names.size())
52006f32e7eSjoerg return true;
52106f32e7eSjoerg }
52206f32e7eSjoerg
52306f32e7eSjoerg // Now check aliases.
52406f32e7eSjoerg for (const GCCRegAlias &GRA : getGCCRegAliases())
52506f32e7eSjoerg for (const char *A : GRA.Aliases) {
52606f32e7eSjoerg if (!A)
52706f32e7eSjoerg break;
52806f32e7eSjoerg if (A == Name)
52906f32e7eSjoerg return true;
53006f32e7eSjoerg }
53106f32e7eSjoerg
53206f32e7eSjoerg return false;
53306f32e7eSjoerg }
53406f32e7eSjoerg
getNormalizedGCCRegisterName(StringRef Name,bool ReturnCanonical) const53506f32e7eSjoerg StringRef TargetInfo::getNormalizedGCCRegisterName(StringRef Name,
53606f32e7eSjoerg bool ReturnCanonical) const {
53706f32e7eSjoerg assert(isValidGCCRegisterName(Name) && "Invalid register passed in");
53806f32e7eSjoerg
53906f32e7eSjoerg // Get rid of any register prefix.
54006f32e7eSjoerg Name = removeGCCRegisterPrefix(Name);
54106f32e7eSjoerg
54206f32e7eSjoerg ArrayRef<const char *> Names = getGCCRegNames();
54306f32e7eSjoerg
54406f32e7eSjoerg // First, check if we have a number.
54506f32e7eSjoerg if (isDigit(Name[0])) {
54606f32e7eSjoerg unsigned n;
54706f32e7eSjoerg if (!Name.getAsInteger(0, n)) {
54806f32e7eSjoerg assert(n < Names.size() && "Out of bounds register number!");
54906f32e7eSjoerg return Names[n];
55006f32e7eSjoerg }
55106f32e7eSjoerg }
55206f32e7eSjoerg
55306f32e7eSjoerg // Check any additional names that we have.
55406f32e7eSjoerg for (const AddlRegName &ARN : getGCCAddlRegNames())
55506f32e7eSjoerg for (const char *AN : ARN.Names) {
55606f32e7eSjoerg if (!AN)
55706f32e7eSjoerg break;
55806f32e7eSjoerg // Make sure the register that the additional name is for is within
55906f32e7eSjoerg // the bounds of the register names from above.
56006f32e7eSjoerg if (AN == Name && ARN.RegNum < Names.size())
56106f32e7eSjoerg return ReturnCanonical ? Names[ARN.RegNum] : Name;
56206f32e7eSjoerg }
56306f32e7eSjoerg
56406f32e7eSjoerg // Now check aliases.
56506f32e7eSjoerg for (const GCCRegAlias &RA : getGCCRegAliases())
56606f32e7eSjoerg for (const char *A : RA.Aliases) {
56706f32e7eSjoerg if (!A)
56806f32e7eSjoerg break;
56906f32e7eSjoerg if (A == Name)
57006f32e7eSjoerg return RA.Register;
57106f32e7eSjoerg }
57206f32e7eSjoerg
57306f32e7eSjoerg return Name;
57406f32e7eSjoerg }
57506f32e7eSjoerg
validateOutputConstraint(ConstraintInfo & Info) const57606f32e7eSjoerg bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const {
57706f32e7eSjoerg const char *Name = Info.getConstraintStr().c_str();
57806f32e7eSjoerg // An output constraint must start with '=' or '+'
57906f32e7eSjoerg if (*Name != '=' && *Name != '+')
58006f32e7eSjoerg return false;
58106f32e7eSjoerg
58206f32e7eSjoerg if (*Name == '+')
58306f32e7eSjoerg Info.setIsReadWrite();
58406f32e7eSjoerg
58506f32e7eSjoerg Name++;
58606f32e7eSjoerg while (*Name) {
58706f32e7eSjoerg switch (*Name) {
58806f32e7eSjoerg default:
58906f32e7eSjoerg if (!validateAsmConstraint(Name, Info)) {
59006f32e7eSjoerg // FIXME: We temporarily return false
59106f32e7eSjoerg // so we can add more constraints as we hit it.
59206f32e7eSjoerg // Eventually, an unknown constraint should just be treated as 'g'.
59306f32e7eSjoerg return false;
59406f32e7eSjoerg }
59506f32e7eSjoerg break;
59606f32e7eSjoerg case '&': // early clobber.
59706f32e7eSjoerg Info.setEarlyClobber();
59806f32e7eSjoerg break;
59906f32e7eSjoerg case '%': // commutative.
60006f32e7eSjoerg // FIXME: Check that there is a another register after this one.
60106f32e7eSjoerg break;
60206f32e7eSjoerg case 'r': // general register.
60306f32e7eSjoerg Info.setAllowsRegister();
60406f32e7eSjoerg break;
60506f32e7eSjoerg case 'm': // memory operand.
60606f32e7eSjoerg case 'o': // offsetable memory operand.
60706f32e7eSjoerg case 'V': // non-offsetable memory operand.
60806f32e7eSjoerg case '<': // autodecrement memory operand.
60906f32e7eSjoerg case '>': // autoincrement memory operand.
61006f32e7eSjoerg Info.setAllowsMemory();
61106f32e7eSjoerg break;
61206f32e7eSjoerg case 'g': // general register, memory operand or immediate integer.
61306f32e7eSjoerg case 'X': // any operand.
61406f32e7eSjoerg Info.setAllowsRegister();
61506f32e7eSjoerg Info.setAllowsMemory();
61606f32e7eSjoerg break;
61706f32e7eSjoerg case ',': // multiple alternative constraint. Pass it.
61806f32e7eSjoerg // Handle additional optional '=' or '+' modifiers.
61906f32e7eSjoerg if (Name[1] == '=' || Name[1] == '+')
62006f32e7eSjoerg Name++;
62106f32e7eSjoerg break;
62206f32e7eSjoerg case '#': // Ignore as constraint.
62306f32e7eSjoerg while (Name[1] && Name[1] != ',')
62406f32e7eSjoerg Name++;
62506f32e7eSjoerg break;
62606f32e7eSjoerg case '?': // Disparage slightly code.
62706f32e7eSjoerg case '!': // Disparage severely.
62806f32e7eSjoerg case '*': // Ignore for choosing register preferences.
62906f32e7eSjoerg case 'i': // Ignore i,n,E,F as output constraints (match from the other
63006f32e7eSjoerg // chars)
63106f32e7eSjoerg case 'n':
63206f32e7eSjoerg case 'E':
63306f32e7eSjoerg case 'F':
63406f32e7eSjoerg break; // Pass them.
63506f32e7eSjoerg }
63606f32e7eSjoerg
63706f32e7eSjoerg Name++;
63806f32e7eSjoerg }
63906f32e7eSjoerg
64006f32e7eSjoerg // Early clobber with a read-write constraint which doesn't permit registers
64106f32e7eSjoerg // is invalid.
64206f32e7eSjoerg if (Info.earlyClobber() && Info.isReadWrite() && !Info.allowsRegister())
64306f32e7eSjoerg return false;
64406f32e7eSjoerg
64506f32e7eSjoerg // If a constraint allows neither memory nor register operands it contains
64606f32e7eSjoerg // only modifiers. Reject it.
64706f32e7eSjoerg return Info.allowsMemory() || Info.allowsRegister();
64806f32e7eSjoerg }
64906f32e7eSjoerg
resolveSymbolicName(const char * & Name,ArrayRef<ConstraintInfo> OutputConstraints,unsigned & Index) const65006f32e7eSjoerg bool TargetInfo::resolveSymbolicName(const char *&Name,
65106f32e7eSjoerg ArrayRef<ConstraintInfo> OutputConstraints,
65206f32e7eSjoerg unsigned &Index) const {
65306f32e7eSjoerg assert(*Name == '[' && "Symbolic name did not start with '['");
65406f32e7eSjoerg Name++;
65506f32e7eSjoerg const char *Start = Name;
65606f32e7eSjoerg while (*Name && *Name != ']')
65706f32e7eSjoerg Name++;
65806f32e7eSjoerg
65906f32e7eSjoerg if (!*Name) {
66006f32e7eSjoerg // Missing ']'
66106f32e7eSjoerg return false;
66206f32e7eSjoerg }
66306f32e7eSjoerg
66406f32e7eSjoerg std::string SymbolicName(Start, Name - Start);
66506f32e7eSjoerg
66606f32e7eSjoerg for (Index = 0; Index != OutputConstraints.size(); ++Index)
66706f32e7eSjoerg if (SymbolicName == OutputConstraints[Index].getName())
66806f32e7eSjoerg return true;
66906f32e7eSjoerg
67006f32e7eSjoerg return false;
67106f32e7eSjoerg }
67206f32e7eSjoerg
validateInputConstraint(MutableArrayRef<ConstraintInfo> OutputConstraints,ConstraintInfo & Info) const67306f32e7eSjoerg bool TargetInfo::validateInputConstraint(
67406f32e7eSjoerg MutableArrayRef<ConstraintInfo> OutputConstraints,
67506f32e7eSjoerg ConstraintInfo &Info) const {
67606f32e7eSjoerg const char *Name = Info.ConstraintStr.c_str();
67706f32e7eSjoerg
67806f32e7eSjoerg if (!*Name)
67906f32e7eSjoerg return false;
68006f32e7eSjoerg
68106f32e7eSjoerg while (*Name) {
68206f32e7eSjoerg switch (*Name) {
68306f32e7eSjoerg default:
68406f32e7eSjoerg // Check if we have a matching constraint
68506f32e7eSjoerg if (*Name >= '0' && *Name <= '9') {
68606f32e7eSjoerg const char *DigitStart = Name;
68706f32e7eSjoerg while (Name[1] >= '0' && Name[1] <= '9')
68806f32e7eSjoerg Name++;
68906f32e7eSjoerg const char *DigitEnd = Name;
69006f32e7eSjoerg unsigned i;
69106f32e7eSjoerg if (StringRef(DigitStart, DigitEnd - DigitStart + 1)
69206f32e7eSjoerg .getAsInteger(10, i))
69306f32e7eSjoerg return false;
69406f32e7eSjoerg
69506f32e7eSjoerg // Check if matching constraint is out of bounds.
69606f32e7eSjoerg if (i >= OutputConstraints.size()) return false;
69706f32e7eSjoerg
69806f32e7eSjoerg // A number must refer to an output only operand.
69906f32e7eSjoerg if (OutputConstraints[i].isReadWrite())
70006f32e7eSjoerg return false;
70106f32e7eSjoerg
70206f32e7eSjoerg // If the constraint is already tied, it must be tied to the
70306f32e7eSjoerg // same operand referenced to by the number.
70406f32e7eSjoerg if (Info.hasTiedOperand() && Info.getTiedOperand() != i)
70506f32e7eSjoerg return false;
70606f32e7eSjoerg
70706f32e7eSjoerg // The constraint should have the same info as the respective
70806f32e7eSjoerg // output constraint.
70906f32e7eSjoerg Info.setTiedOperand(i, OutputConstraints[i]);
71006f32e7eSjoerg } else if (!validateAsmConstraint(Name, Info)) {
71106f32e7eSjoerg // FIXME: This error return is in place temporarily so we can
71206f32e7eSjoerg // add more constraints as we hit it. Eventually, an unknown
71306f32e7eSjoerg // constraint should just be treated as 'g'.
71406f32e7eSjoerg return false;
71506f32e7eSjoerg }
71606f32e7eSjoerg break;
71706f32e7eSjoerg case '[': {
71806f32e7eSjoerg unsigned Index = 0;
71906f32e7eSjoerg if (!resolveSymbolicName(Name, OutputConstraints, Index))
72006f32e7eSjoerg return false;
72106f32e7eSjoerg
72206f32e7eSjoerg // If the constraint is already tied, it must be tied to the
72306f32e7eSjoerg // same operand referenced to by the number.
72406f32e7eSjoerg if (Info.hasTiedOperand() && Info.getTiedOperand() != Index)
72506f32e7eSjoerg return false;
72606f32e7eSjoerg
72706f32e7eSjoerg // A number must refer to an output only operand.
72806f32e7eSjoerg if (OutputConstraints[Index].isReadWrite())
72906f32e7eSjoerg return false;
73006f32e7eSjoerg
73106f32e7eSjoerg Info.setTiedOperand(Index, OutputConstraints[Index]);
73206f32e7eSjoerg break;
73306f32e7eSjoerg }
73406f32e7eSjoerg case '%': // commutative
73506f32e7eSjoerg // FIXME: Fail if % is used with the last operand.
73606f32e7eSjoerg break;
73706f32e7eSjoerg case 'i': // immediate integer.
73806f32e7eSjoerg break;
73906f32e7eSjoerg case 'n': // immediate integer with a known value.
74006f32e7eSjoerg Info.setRequiresImmediate();
74106f32e7eSjoerg break;
74206f32e7eSjoerg case 'I': // Various constant constraints with target-specific meanings.
74306f32e7eSjoerg case 'J':
74406f32e7eSjoerg case 'K':
74506f32e7eSjoerg case 'L':
74606f32e7eSjoerg case 'M':
74706f32e7eSjoerg case 'N':
74806f32e7eSjoerg case 'O':
74906f32e7eSjoerg case 'P':
75006f32e7eSjoerg if (!validateAsmConstraint(Name, Info))
75106f32e7eSjoerg return false;
75206f32e7eSjoerg break;
75306f32e7eSjoerg case 'r': // general register.
75406f32e7eSjoerg Info.setAllowsRegister();
75506f32e7eSjoerg break;
75606f32e7eSjoerg case 'm': // memory operand.
75706f32e7eSjoerg case 'o': // offsettable memory operand.
75806f32e7eSjoerg case 'V': // non-offsettable memory operand.
75906f32e7eSjoerg case '<': // autodecrement memory operand.
76006f32e7eSjoerg case '>': // autoincrement memory operand.
76106f32e7eSjoerg Info.setAllowsMemory();
76206f32e7eSjoerg break;
76306f32e7eSjoerg case 'g': // general register, memory operand or immediate integer.
76406f32e7eSjoerg case 'X': // any operand.
76506f32e7eSjoerg Info.setAllowsRegister();
76606f32e7eSjoerg Info.setAllowsMemory();
76706f32e7eSjoerg break;
76806f32e7eSjoerg case 'E': // immediate floating point.
76906f32e7eSjoerg case 'F': // immediate floating point.
77006f32e7eSjoerg case 'p': // address operand.
77106f32e7eSjoerg break;
77206f32e7eSjoerg case ',': // multiple alternative constraint. Ignore comma.
77306f32e7eSjoerg break;
77406f32e7eSjoerg case '#': // Ignore as constraint.
77506f32e7eSjoerg while (Name[1] && Name[1] != ',')
77606f32e7eSjoerg Name++;
77706f32e7eSjoerg break;
77806f32e7eSjoerg case '?': // Disparage slightly code.
77906f32e7eSjoerg case '!': // Disparage severely.
78006f32e7eSjoerg case '*': // Ignore for choosing register preferences.
78106f32e7eSjoerg break; // Pass them.
78206f32e7eSjoerg }
78306f32e7eSjoerg
78406f32e7eSjoerg Name++;
78506f32e7eSjoerg }
78606f32e7eSjoerg
78706f32e7eSjoerg return true;
78806f32e7eSjoerg }
78906f32e7eSjoerg
CheckFixedPointBits() const79006f32e7eSjoerg void TargetInfo::CheckFixedPointBits() const {
79106f32e7eSjoerg // Check that the number of fractional and integral bits (and maybe sign) can
79206f32e7eSjoerg // fit into the bits given for a fixed point type.
79306f32e7eSjoerg assert(ShortAccumScale + getShortAccumIBits() + 1 <= ShortAccumWidth);
79406f32e7eSjoerg assert(AccumScale + getAccumIBits() + 1 <= AccumWidth);
79506f32e7eSjoerg assert(LongAccumScale + getLongAccumIBits() + 1 <= LongAccumWidth);
79606f32e7eSjoerg assert(getUnsignedShortAccumScale() + getUnsignedShortAccumIBits() <=
79706f32e7eSjoerg ShortAccumWidth);
79806f32e7eSjoerg assert(getUnsignedAccumScale() + getUnsignedAccumIBits() <= AccumWidth);
79906f32e7eSjoerg assert(getUnsignedLongAccumScale() + getUnsignedLongAccumIBits() <=
80006f32e7eSjoerg LongAccumWidth);
80106f32e7eSjoerg
80206f32e7eSjoerg assert(getShortFractScale() + 1 <= ShortFractWidth);
80306f32e7eSjoerg assert(getFractScale() + 1 <= FractWidth);
80406f32e7eSjoerg assert(getLongFractScale() + 1 <= LongFractWidth);
80506f32e7eSjoerg assert(getUnsignedShortFractScale() <= ShortFractWidth);
80606f32e7eSjoerg assert(getUnsignedFractScale() <= FractWidth);
80706f32e7eSjoerg assert(getUnsignedLongFractScale() <= LongFractWidth);
80806f32e7eSjoerg
80906f32e7eSjoerg // Each unsigned fract type has either the same number of fractional bits
81006f32e7eSjoerg // as, or one more fractional bit than, its corresponding signed fract type.
81106f32e7eSjoerg assert(getShortFractScale() == getUnsignedShortFractScale() ||
81206f32e7eSjoerg getShortFractScale() == getUnsignedShortFractScale() - 1);
81306f32e7eSjoerg assert(getFractScale() == getUnsignedFractScale() ||
81406f32e7eSjoerg getFractScale() == getUnsignedFractScale() - 1);
81506f32e7eSjoerg assert(getLongFractScale() == getUnsignedLongFractScale() ||
81606f32e7eSjoerg getLongFractScale() == getUnsignedLongFractScale() - 1);
81706f32e7eSjoerg
81806f32e7eSjoerg // When arranged in order of increasing rank (see 6.3.1.3a), the number of
81906f32e7eSjoerg // fractional bits is nondecreasing for each of the following sets of
82006f32e7eSjoerg // fixed-point types:
82106f32e7eSjoerg // - signed fract types
82206f32e7eSjoerg // - unsigned fract types
82306f32e7eSjoerg // - signed accum types
82406f32e7eSjoerg // - unsigned accum types.
82506f32e7eSjoerg assert(getLongFractScale() >= getFractScale() &&
82606f32e7eSjoerg getFractScale() >= getShortFractScale());
82706f32e7eSjoerg assert(getUnsignedLongFractScale() >= getUnsignedFractScale() &&
82806f32e7eSjoerg getUnsignedFractScale() >= getUnsignedShortFractScale());
82906f32e7eSjoerg assert(LongAccumScale >= AccumScale && AccumScale >= ShortAccumScale);
83006f32e7eSjoerg assert(getUnsignedLongAccumScale() >= getUnsignedAccumScale() &&
83106f32e7eSjoerg getUnsignedAccumScale() >= getUnsignedShortAccumScale());
83206f32e7eSjoerg
83306f32e7eSjoerg // When arranged in order of increasing rank (see 6.3.1.3a), the number of
83406f32e7eSjoerg // integral bits is nondecreasing for each of the following sets of
83506f32e7eSjoerg // fixed-point types:
83606f32e7eSjoerg // - signed accum types
83706f32e7eSjoerg // - unsigned accum types
83806f32e7eSjoerg assert(getLongAccumIBits() >= getAccumIBits() &&
83906f32e7eSjoerg getAccumIBits() >= getShortAccumIBits());
84006f32e7eSjoerg assert(getUnsignedLongAccumIBits() >= getUnsignedAccumIBits() &&
84106f32e7eSjoerg getUnsignedAccumIBits() >= getUnsignedShortAccumIBits());
84206f32e7eSjoerg
84306f32e7eSjoerg // Each signed accum type has at least as many integral bits as its
84406f32e7eSjoerg // corresponding unsigned accum type.
84506f32e7eSjoerg assert(getShortAccumIBits() >= getUnsignedShortAccumIBits());
84606f32e7eSjoerg assert(getAccumIBits() >= getUnsignedAccumIBits());
84706f32e7eSjoerg assert(getLongAccumIBits() >= getUnsignedLongAccumIBits());
84806f32e7eSjoerg }
84906f32e7eSjoerg
copyAuxTarget(const TargetInfo * Aux)85006f32e7eSjoerg void TargetInfo::copyAuxTarget(const TargetInfo *Aux) {
85106f32e7eSjoerg auto *Target = static_cast<TransferrableTargetInfo*>(this);
85206f32e7eSjoerg auto *Src = static_cast<const TransferrableTargetInfo*>(Aux);
85306f32e7eSjoerg *Target = *Src;
85406f32e7eSjoerg }
855