123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667 |
- //===--- TargetInfo.cpp - Information about Target machine ----------------===//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- //
- // This file implements the TargetInfo and TargetInfoImpl interfaces.
- //
- //===----------------------------------------------------------------------===//
- #include "clang/Basic/TargetInfo.h"
- #include "clang/Basic/AddressSpaces.h"
- #include "clang/Basic/CharInfo.h"
- #include "clang/Basic/LangOptions.h"
- #include "llvm/ADT/APFloat.h"
- #include "llvm/ADT/STLExtras.h"
- #include "llvm/Support/ErrorHandling.h"
- #include <cstdlib>
- using namespace clang;
- static const LangAS::Map DefaultAddrSpaceMap = { 0 };
- // TargetInfo Constructor.
- TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
- // Set defaults. Defaults are set for a 32-bit RISC platform, like PPC or
- // SPARC. These should be overridden by concrete targets as needed.
- BigEndian = true;
- TLSSupported = true;
- NoAsmVariants = false;
- PointerWidth = PointerAlign = 32;
- BoolWidth = BoolAlign = 8;
- IntWidth = IntAlign = 32;
- LongWidth = LongAlign = 32;
- LongLongWidth = LongLongAlign = 64;
- SuitableAlign = 64;
- DefaultAlignForAttributeAligned = 128;
- MinGlobalAlign = 0;
- HalfWidth = 16;
- HalfAlign = 16;
- FloatWidth = 32;
- FloatAlign = 32;
- DoubleWidth = 64;
- DoubleAlign = 64;
- LongDoubleWidth = 64;
- LongDoubleAlign = 64;
- LargeArrayMinWidth = 0;
- LargeArrayAlign = 0;
- MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0;
- MaxVectorAlign = 0;
- MaxTLSAlign = 0;
- SimdDefaultAlign = 0;
- SizeType = UnsignedLong;
- PtrDiffType = SignedLong;
- IntMaxType = SignedLongLong;
- IntPtrType = SignedLong;
- WCharType = SignedInt;
- WIntType = SignedInt;
- Char16Type = UnsignedShort;
- Char32Type = UnsignedInt;
- Int64Type = SignedLongLong;
- SigAtomicType = SignedInt;
- ProcessIDType = SignedInt;
- UseSignedCharForObjCBool = true;
- UseBitFieldTypeAlignment = true;
- UseZeroLengthBitfieldAlignment = false;
- ZeroLengthBitfieldBoundary = 0;
- HalfFormat = &llvm::APFloat::IEEEhalf;
- FloatFormat = &llvm::APFloat::IEEEsingle;
- DoubleFormat = &llvm::APFloat::IEEEdouble;
- LongDoubleFormat = &llvm::APFloat::IEEEdouble;
- DescriptionString = nullptr;
- UserLabelPrefix = "_";
- MCountName = "mcount";
- RegParmMax = 0;
- SSERegParmMax = 0;
- HasAlignMac68kSupport = false;
- // Default to no types using fpret.
- RealTypeUsesObjCFPRet = 0;
- // Default to not using fp2ret for __Complex long double
- ComplexLongDoubleUsesFP2Ret = false;
- // Set the C++ ABI based on the triple.
- TheCXXABI.set(Triple.isKnownWindowsMSVCEnvironment()
- ? TargetCXXABI::Microsoft
- : TargetCXXABI::GenericItanium);
- // Default to an empty address space map.
- AddrSpaceMap = &DefaultAddrSpaceMap;
- UseAddrSpaceMapMangling = false;
- // Default to an unknown platform name.
- PlatformName = "unknown";
- PlatformMinVersion = VersionTuple();
- }
- // Out of line virtual dtor for TargetInfo.
- TargetInfo::~TargetInfo() {}
- /// getTypeName - Return the user string for the specified integer type enum.
- /// For example, SignedShort -> "short".
- const char *TargetInfo::getTypeName(IntType T) {
- switch (T) {
- default: llvm_unreachable("not an integer!");
- case SignedChar: return "signed char";
- case UnsignedChar: return "unsigned char";
- case SignedShort: return "short";
- case UnsignedShort: return "unsigned short";
- case SignedInt: return "int";
- case UnsignedInt: return "unsigned int";
- case SignedLong: return "long int";
- case UnsignedLong: return "long unsigned int";
- case SignedLongLong: return "long long int";
- case UnsignedLongLong: return "long long unsigned int";
- }
- }
- /// getTypeConstantSuffix - Return the constant suffix for the specified
- /// integer type enum. For example, SignedLong -> "L".
- const char *TargetInfo::getTypeConstantSuffix(IntType T) const {
- switch (T) {
- default: llvm_unreachable("not an integer!");
- case SignedChar:
- case SignedShort:
- case SignedInt: return "";
- case SignedLong: return "L";
- case SignedLongLong: return "LL";
- case UnsignedChar:
- if (getCharWidth() < getIntWidth())
- return "";
- case UnsignedShort:
- if (getShortWidth() < getIntWidth())
- return "";
- case UnsignedInt: return "U";
- case UnsignedLong: return "UL";
- case UnsignedLongLong: return "ULL";
- }
- }
- /// getTypeFormatModifier - Return the printf format modifier for the
- /// specified integer type enum. For example, SignedLong -> "l".
- const char *TargetInfo::getTypeFormatModifier(IntType T) {
- switch (T) {
- default: llvm_unreachable("not an integer!");
- case SignedChar:
- case UnsignedChar: return "hh";
- case SignedShort:
- case UnsignedShort: return "h";
- case SignedInt:
- case UnsignedInt: return "";
- case SignedLong:
- case UnsignedLong: return "l";
- case SignedLongLong:
- case UnsignedLongLong: return "ll";
- }
- }
- /// getTypeWidth - Return the width (in bits) of the specified integer type
- /// enum. For example, SignedInt -> getIntWidth().
- unsigned TargetInfo::getTypeWidth(IntType T) const {
- switch (T) {
- default: llvm_unreachable("not an integer!");
- case SignedChar:
- case UnsignedChar: return getCharWidth();
- case SignedShort:
- case UnsignedShort: return getShortWidth();
- case SignedInt:
- case UnsignedInt: return getIntWidth();
- case SignedLong:
- case UnsignedLong: return getLongWidth();
- case SignedLongLong:
- case UnsignedLongLong: return getLongLongWidth();
- };
- }
- TargetInfo::IntType TargetInfo::getIntTypeByWidth(
- unsigned BitWidth, bool IsSigned) const {
- if (getCharWidth() == BitWidth)
- return IsSigned ? SignedChar : UnsignedChar;
- if (getShortWidth() == BitWidth)
- return IsSigned ? SignedShort : UnsignedShort;
- if (getIntWidth() == BitWidth)
- return IsSigned ? SignedInt : UnsignedInt;
- if (getLongWidth() == BitWidth)
- return IsSigned ? SignedLong : UnsignedLong;
- if (getLongLongWidth() == BitWidth)
- return IsSigned ? SignedLongLong : UnsignedLongLong;
- return NoInt;
- }
- TargetInfo::IntType TargetInfo::getLeastIntTypeByWidth(unsigned BitWidth,
- bool IsSigned) const {
- if (getCharWidth() >= BitWidth)
- return IsSigned ? SignedChar : UnsignedChar;
- if (getShortWidth() >= BitWidth)
- return IsSigned ? SignedShort : UnsignedShort;
- if (getIntWidth() >= BitWidth)
- return IsSigned ? SignedInt : UnsignedInt;
- if (getLongWidth() >= BitWidth)
- return IsSigned ? SignedLong : UnsignedLong;
- if (getLongLongWidth() >= BitWidth)
- return IsSigned ? SignedLongLong : UnsignedLongLong;
- return NoInt;
- }
- TargetInfo::RealType TargetInfo::getRealTypeByWidth(unsigned BitWidth) const {
- if (getFloatWidth() == BitWidth)
- return Float;
- if (getDoubleWidth() == BitWidth)
- return Double;
- switch (BitWidth) {
- case 96:
- if (&getLongDoubleFormat() == &llvm::APFloat::x87DoubleExtended)
- return LongDouble;
- break;
- case 128:
- if (&getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble ||
- &getLongDoubleFormat() == &llvm::APFloat::IEEEquad)
- return LongDouble;
- break;
- }
- return NoFloat;
- }
- /// getTypeAlign - Return the alignment (in bits) of the specified integer type
- /// enum. For example, SignedInt -> getIntAlign().
- unsigned TargetInfo::getTypeAlign(IntType T) const {
- switch (T) {
- default: llvm_unreachable("not an integer!");
- case SignedChar:
- case UnsignedChar: return getCharAlign();
- case SignedShort:
- case UnsignedShort: return getShortAlign();
- case SignedInt:
- case UnsignedInt: return getIntAlign();
- case SignedLong:
- case UnsignedLong: return getLongAlign();
- case SignedLongLong:
- case UnsignedLongLong: return getLongLongAlign();
- };
- }
- /// isTypeSigned - Return whether an integer types is signed. Returns true if
- /// the type is signed; false otherwise.
- bool TargetInfo::isTypeSigned(IntType T) {
- switch (T) {
- default: llvm_unreachable("not an integer!");
- case SignedChar:
- case SignedShort:
- case SignedInt:
- case SignedLong:
- case SignedLongLong:
- return true;
- case UnsignedChar:
- case UnsignedShort:
- case UnsignedInt:
- case UnsignedLong:
- case UnsignedLongLong:
- return false;
- };
- }
- /// adjust - Set forced language options.
- /// Apply changes to the target information with respect to certain
- /// language options which change the target configuration.
- void TargetInfo::adjust(const LangOptions &Opts) {
- if (Opts.NoBitFieldTypeAlign)
- UseBitFieldTypeAlignment = false;
- if (Opts.ShortWChar)
- WCharType = UnsignedShort;
- if (Opts.OpenCL) {
- // OpenCL C requires specific widths for types, irrespective of
- // what these normally are for the target.
- // We also define long long and long double here, although the
- // OpenCL standard only mentions these as "reserved".
- IntWidth = IntAlign = 32;
- LongWidth = LongAlign = 64;
- LongLongWidth = LongLongAlign = 128;
- HalfWidth = HalfAlign = 16;
- FloatWidth = FloatAlign = 32;
-
- // Embedded 32-bit targets (OpenCL EP) might have double C type
- // defined as float. Let's not override this as it might lead
- // to generating illegal code that uses 64bit doubles.
- if (DoubleWidth != FloatWidth) {
- DoubleWidth = DoubleAlign = 64;
- DoubleFormat = &llvm::APFloat::IEEEdouble;
- }
- LongDoubleWidth = LongDoubleAlign = 128;
- assert(PointerWidth == 32 || PointerWidth == 64);
- bool Is32BitArch = PointerWidth == 32;
- SizeType = Is32BitArch ? UnsignedInt : UnsignedLong;
- PtrDiffType = Is32BitArch ? SignedInt : SignedLong;
- IntPtrType = Is32BitArch ? SignedInt : SignedLong;
- IntMaxType = SignedLongLong;
- Int64Type = SignedLong;
- HalfFormat = &llvm::APFloat::IEEEhalf;
- FloatFormat = &llvm::APFloat::IEEEsingle;
- LongDoubleFormat = &llvm::APFloat::IEEEquad;
- }
- }
- //===----------------------------------------------------------------------===//
- static StringRef removeGCCRegisterPrefix(StringRef Name) {
- if (Name[0] == '%' || Name[0] == '#')
- Name = Name.substr(1);
- return Name;
- }
- /// isValidClobber - Returns whether the passed in string is
- /// a valid clobber in an inline asm statement. This is used by
- /// Sema.
- bool TargetInfo::isValidClobber(StringRef Name) const {
- return (isValidGCCRegisterName(Name) ||
- Name == "memory" || Name == "cc");
- }
- /// isValidGCCRegisterName - Returns whether the passed in string
- /// is a valid register name according to GCC. This is used by Sema for
- /// inline asm statements.
- bool TargetInfo::isValidGCCRegisterName(StringRef Name) const {
- if (Name.empty())
- return false;
- const char * const *Names;
- unsigned NumNames;
- // Get rid of any register prefix.
- Name = removeGCCRegisterPrefix(Name);
- if (Name.empty())
- return false;
- getGCCRegNames(Names, NumNames);
- // If we have a number it maps to an entry in the register name array.
- if (isDigit(Name[0])) {
- int n;
- if (!Name.getAsInteger(0, n))
- return n >= 0 && (unsigned)n < NumNames;
- }
- // Check register names.
- for (unsigned i = 0; i < NumNames; i++) {
- if (Name == Names[i])
- return true;
- }
- // Check any additional names that we have.
- const AddlRegName *AddlNames;
- unsigned NumAddlNames;
- getGCCAddlRegNames(AddlNames, NumAddlNames);
- for (unsigned i = 0; i < NumAddlNames; i++)
- for (unsigned j = 0; j < llvm::array_lengthof(AddlNames[i].Names); j++) {
- if (!AddlNames[i].Names[j])
- break;
- // Make sure the register that the additional name is for is within
- // the bounds of the register names from above.
- if (AddlNames[i].Names[j] == Name && AddlNames[i].RegNum < NumNames)
- return true;
- }
- // Now check aliases.
- const GCCRegAlias *Aliases;
- unsigned NumAliases;
- getGCCRegAliases(Aliases, NumAliases);
- for (unsigned i = 0; i < NumAliases; i++) {
- for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
- if (!Aliases[i].Aliases[j])
- break;
- if (Aliases[i].Aliases[j] == Name)
- return true;
- }
- }
- return false;
- }
- StringRef
- TargetInfo::getNormalizedGCCRegisterName(StringRef Name) const {
- assert(isValidGCCRegisterName(Name) && "Invalid register passed in");
- // Get rid of any register prefix.
- Name = removeGCCRegisterPrefix(Name);
- const char * const *Names;
- unsigned NumNames;
- getGCCRegNames(Names, NumNames);
- // First, check if we have a number.
- if (isDigit(Name[0])) {
- int n;
- if (!Name.getAsInteger(0, n)) {
- assert(n >= 0 && (unsigned)n < NumNames &&
- "Out of bounds register number!");
- return Names[n];
- }
- }
- // Check any additional names that we have.
- const AddlRegName *AddlNames;
- unsigned NumAddlNames;
- getGCCAddlRegNames(AddlNames, NumAddlNames);
- for (unsigned i = 0; i < NumAddlNames; i++)
- for (unsigned j = 0; j < llvm::array_lengthof(AddlNames[i].Names); j++) {
- if (!AddlNames[i].Names[j])
- break;
- // Make sure the register that the additional name is for is within
- // the bounds of the register names from above.
- if (AddlNames[i].Names[j] == Name && AddlNames[i].RegNum < NumNames)
- return Name;
- }
- // Now check aliases.
- const GCCRegAlias *Aliases;
- unsigned NumAliases;
- getGCCRegAliases(Aliases, NumAliases);
- for (unsigned i = 0; i < NumAliases; i++) {
- for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) {
- if (!Aliases[i].Aliases[j])
- break;
- if (Aliases[i].Aliases[j] == Name)
- return Aliases[i].Register;
- }
- }
- return Name;
- }
- bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const {
- const char *Name = Info.getConstraintStr().c_str();
- // An output constraint must start with '=' or '+'
- if (*Name != '=' && *Name != '+')
- return false;
- if (*Name == '+')
- Info.setIsReadWrite();
- Name++;
- while (*Name) {
- switch (*Name) {
- default:
- if (!validateAsmConstraint(Name, Info)) {
- // FIXME: We temporarily return false
- // so we can add more constraints as we hit it.
- // Eventually, an unknown constraint should just be treated as 'g'.
- return false;
- }
- break;
- case '&': // early clobber.
- Info.setEarlyClobber();
- break;
- case '%': // commutative.
- // FIXME: Check that there is a another register after this one.
- break;
- case 'r': // general register.
- Info.setAllowsRegister();
- break;
- case 'm': // memory operand.
- case 'o': // offsetable memory operand.
- case 'V': // non-offsetable memory operand.
- case '<': // autodecrement memory operand.
- case '>': // autoincrement memory operand.
- Info.setAllowsMemory();
- break;
- case 'g': // general register, memory operand or immediate integer.
- case 'X': // any operand.
- Info.setAllowsRegister();
- Info.setAllowsMemory();
- break;
- case ',': // multiple alternative constraint. Pass it.
- // Handle additional optional '=' or '+' modifiers.
- if (Name[1] == '=' || Name[1] == '+')
- Name++;
- break;
- case '#': // Ignore as constraint.
- while (Name[1] && Name[1] != ',')
- Name++;
- break;
- case '?': // Disparage slightly code.
- case '!': // Disparage severely.
- case '*': // Ignore for choosing register preferences.
- break; // Pass them.
- }
- Name++;
- }
- // Early clobber with a read-write constraint which doesn't permit registers
- // is invalid.
- if (Info.earlyClobber() && Info.isReadWrite() && !Info.allowsRegister())
- return false;
- // If a constraint allows neither memory nor register operands it contains
- // only modifiers. Reject it.
- return Info.allowsMemory() || Info.allowsRegister();
- }
- bool TargetInfo::resolveSymbolicName(const char *&Name,
- ConstraintInfo *OutputConstraints,
- unsigned NumOutputs,
- unsigned &Index) const {
- assert(*Name == '[' && "Symbolic name did not start with '['");
- Name++;
- const char *Start = Name;
- while (*Name && *Name != ']')
- Name++;
- if (!*Name) {
- // Missing ']'
- return false;
- }
- std::string SymbolicName(Start, Name - Start);
- for (Index = 0; Index != NumOutputs; ++Index)
- if (SymbolicName == OutputConstraints[Index].getName())
- return true;
- return false;
- }
- bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints,
- unsigned NumOutputs,
- ConstraintInfo &Info) const {
- const char *Name = Info.ConstraintStr.c_str();
- if (!*Name)
- return false;
- while (*Name) {
- switch (*Name) {
- default:
- // Check if we have a matching constraint
- if (*Name >= '0' && *Name <= '9') {
- const char *DigitStart = Name;
- while (Name[1] >= '0' && Name[1] <= '9')
- Name++;
- const char *DigitEnd = Name;
- unsigned i;
- if (StringRef(DigitStart, DigitEnd - DigitStart + 1)
- .getAsInteger(10, i))
- return false;
- // Check if matching constraint is out of bounds.
- if (i >= NumOutputs) return false;
- // A number must refer to an output only operand.
- if (OutputConstraints[i].isReadWrite())
- return false;
- // If the constraint is already tied, it must be tied to the
- // same operand referenced to by the number.
- if (Info.hasTiedOperand() && Info.getTiedOperand() != i)
- return false;
- // The constraint should have the same info as the respective
- // output constraint.
- Info.setTiedOperand(i, OutputConstraints[i]);
- } else if (!validateAsmConstraint(Name, Info)) {
- // FIXME: This error return is in place temporarily so we can
- // add more constraints as we hit it. Eventually, an unknown
- // constraint should just be treated as 'g'.
- return false;
- }
- break;
- case '[': {
- unsigned Index = 0;
- if (!resolveSymbolicName(Name, OutputConstraints, NumOutputs, Index))
- return false;
- // If the constraint is already tied, it must be tied to the
- // same operand referenced to by the number.
- if (Info.hasTiedOperand() && Info.getTiedOperand() != Index)
- return false;
- // A number must refer to an output only operand.
- if (OutputConstraints[Index].isReadWrite())
- return false;
- Info.setTiedOperand(Index, OutputConstraints[Index]);
- break;
- }
- case '%': // commutative
- // FIXME: Fail if % is used with the last operand.
- break;
- case 'i': // immediate integer.
- case 'n': // immediate integer with a known value.
- break;
- case 'I': // Various constant constraints with target-specific meanings.
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- if (!validateAsmConstraint(Name, Info))
- return false;
- break;
- case 'r': // general register.
- Info.setAllowsRegister();
- break;
- case 'm': // memory operand.
- case 'o': // offsettable memory operand.
- case 'V': // non-offsettable memory operand.
- case '<': // autodecrement memory operand.
- case '>': // autoincrement memory operand.
- Info.setAllowsMemory();
- break;
- case 'g': // general register, memory operand or immediate integer.
- case 'X': // any operand.
- Info.setAllowsRegister();
- Info.setAllowsMemory();
- break;
- case 'E': // immediate floating point.
- case 'F': // immediate floating point.
- case 'p': // address operand.
- break;
- case ',': // multiple alternative constraint. Ignore comma.
- break;
- case '#': // Ignore as constraint.
- while (Name[1] && Name[1] != ',')
- Name++;
- break;
- case '?': // Disparage slightly code.
- case '!': // Disparage severely.
- case '*': // Ignore for choosing register preferences.
- break; // Pass them.
- }
- Name++;
- }
- return true;
- }
- bool TargetCXXABI::tryParse(llvm::StringRef name) {
- const Kind unknown = static_cast<Kind>(-1);
- Kind kind = llvm::StringSwitch<Kind>(name)
- .Case("arm", GenericARM)
- .Case("ios", iOS)
- .Case("itanium", GenericItanium)
- .Case("microsoft", Microsoft)
- .Case("mips", GenericMIPS)
- .Default(unknown);
- if (kind == unknown) return false;
- set(kind);
- return true;
- }
|