diff --git a/llvm/include/llvm/Target/TargetData.h b/llvm/include/llvm/Target/TargetData.h index 26fd1870ac39..d116f392fb31 100644 --- a/llvm/include/llvm/Target/TargetData.h +++ b/llvm/include/llvm/Target/TargetData.h @@ -44,7 +44,7 @@ enum AlignTypeEnum { AGGREGATE_ALIGN = 'a', ///< Aggregate alignment STACK_ALIGN = 's' ///< Stack objects alignment }; - + /// Target alignment element. /// /// Stores the alignment data associated with a given alignment type (pointer, @@ -80,7 +80,7 @@ private: unsigned StackNaturalAlign; ///< Stack natural alignment SmallVector LegalIntWidths; ///< Legal Integers. - + /// Alignments- Where the primitive type alignment data is stored. /// /// @sa init(). @@ -88,7 +88,7 @@ private: /// pointers vs. 64-bit pointers by extending TargetAlignment, but for now, /// we don't. SmallVector Alignments; - + /// InvalidAlignmentElem - This member is a signal that a requested alignment /// type and bit width were not found in the SmallVector. static const TargetAlignElem InvalidAlignmentElem; @@ -112,19 +112,30 @@ private: return &align != &InvalidAlignmentElem; } + /// Initialise a TargetData object with default values, ensure that the + /// target data pass is registered. + void init(); + public: /// Default ctor. /// /// @note This has to exist, because this is a pass, but it should never be /// used. TargetData(); - + /// Constructs a TargetData from a specification string. See init(). explicit TargetData(StringRef TargetDescription) : ImmutablePass(ID) { - init(TargetDescription); + std::string errMsg = parseSpecifier(TargetDescription, this); + assert(errMsg == "" && "Invalid target data layout string."); + (void)errMsg; } + /// Parses a target data specification string. Returns an error message + /// if the string is malformed, or the empty string on success. Optionally + /// initialises a TargetData object if passed a non-null pointer. + static std::string parseSpecifier(StringRef TargetDescription, TargetData* td = 0); + /// Initialize target data from properties stored in the module. explicit TargetData(const Module *M); @@ -141,9 +152,6 @@ public: ~TargetData(); // Not virtual, do not subclass this class - //! Parse a target data layout string and initialize TargetData alignments. - void init(StringRef TargetDescription); - /// Target endianness... bool isLittleEndian() const { return LittleEndian; } bool isBigEndian() const { return !LittleEndian; } @@ -152,7 +160,7 @@ public: /// TargetData. This representation is in the same format accepted by the /// string constructor above. std::string getStringRepresentation() const; - + /// isLegalInteger - This function returns true if the specified type is /// known to be a native integer type supported by the CPU. For example, /// i64 is not native on most 32-bit CPUs and i37 is not native on any known @@ -166,7 +174,7 @@ public: return true; return false; } - + bool isIllegalInteger(unsigned Width) const { return !isLegalInteger(Width); } @@ -251,11 +259,11 @@ public: /// getABITypeAlignment - Return the minimum ABI-required alignment for the /// specified type. unsigned getABITypeAlignment(Type *Ty) const; - + /// getABIIntegerTypeAlignment - Return the minimum ABI-required alignment for /// an integer type of the specified bitwidth. unsigned getABIIntegerTypeAlignment(unsigned BitWidth) const; - + /// getCallFrameTypeAlignment - Return the minimum ABI-required alignment /// for the specified type when it is part of a call frame. @@ -305,7 +313,7 @@ public: assert((Alignment & (Alignment-1)) == 0 && "Alignment must be power of 2!"); return (Val + (Alignment-1)) & ~UIntTy(Alignment-1); } - + static char ID; // Pass identification, replacement for typeid }; diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index cafaab01afd9..eb6afd36c772 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -24,6 +24,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetData.h" using namespace llvm; static std::string getTypeString(Type *T) { @@ -260,9 +261,14 @@ bool LLParser::ParseTargetDefinition() { return false; case lltok::kw_datalayout: Lex.Lex(); + LocTy SpecifierLoc = Lex.getLoc(); if (ParseToken(lltok::equal, "expected '=' after target datalayout") || ParseStringConstant(Str)) return true; + std::string errMsg = TargetData::parseSpecifier(Str); + if (errMsg != "") { + return Error(SpecifierLoc, errMsg); + } M->setDataLayout(Str); return false; } diff --git a/llvm/lib/Target/TargetData.cpp b/llvm/lib/Target/TargetData.cpp index bd6a6b67beb9..ff60e0b29c74 100644 --- a/llvm/lib/Target/TargetData.cpp +++ b/llvm/lib/Target/TargetData.cpp @@ -125,15 +125,15 @@ const TargetAlignElem TargetData::InvalidAlignmentElem = //===----------------------------------------------------------------------===// /// getInt - Get an integer ignoring errors. -static unsigned getInt(StringRef R) { - unsigned Result = 0; +static int getInt(StringRef R) { + int Result = 0; R.getAsInteger(10, Result); return Result; } -void TargetData::init(StringRef Desc) { +void TargetData::init() { initializeTargetDataPass(*PassRegistry::getPassRegistry()); - + LayoutMap = 0; LittleEndian = false; PointerMemSize = 8; @@ -152,6 +152,12 @@ void TargetData::init(StringRef Desc) { setAlignment(VECTOR_ALIGN, 8, 8, 64); // v2i32, v1i64, ... setAlignment(VECTOR_ALIGN, 16, 16, 128); // v16i8, v8i16, v4i32, ... setAlignment(AGGREGATE_ALIGN, 0, 8, 0); // struct +} + +std::string TargetData::parseSpecifier(StringRef Desc, TargetData *td) { + + if (td) + td->init(); while (!Desc.empty()) { std::pair Split = Desc.split('-'); @@ -169,28 +175,54 @@ void TargetData::init(StringRef Desc) { switch (Specifier[0]) { case 'E': - LittleEndian = false; + if (td) + td->LittleEndian = false; break; case 'e': - LittleEndian = true; + if (td) + td->LittleEndian = true; break; - case 'p': + case 'p': { + // Pointer size. Split = Token.split(':'); - PointerMemSize = getInt(Split.first) / 8; + int PointerMemSizeBits = getInt(Split.first); + if (PointerMemSizeBits < 0 || PointerMemSizeBits % 8 != 0) + return "invalid pointer size, must be a positive 8-bit multiple"; + if (td) + td->PointerMemSize = PointerMemSizeBits / 8; + + // Pointer ABI alignment. Split = Split.second.split(':'); - PointerABIAlign = getInt(Split.first) / 8; + int PointerABIAlignBits = getInt(Split.first); + if (PointerABIAlignBits < 0 || PointerABIAlignBits % 8 != 0) { + return "invalid pointer ABI alignment, " + "must be a positive 8-bit multiple"; + } + if (td) + td->PointerABIAlign = PointerABIAlignBits / 8; + + // Pointer preferred alignment. Split = Split.second.split(':'); - PointerPrefAlign = getInt(Split.first) / 8; - if (PointerPrefAlign == 0) - PointerPrefAlign = PointerABIAlign; + int PointerPrefAlignBits = getInt(Split.first); + if (PointerPrefAlignBits < 0 || PointerPrefAlignBits % 8 != 0) { + return "invalid pointer preferred alignment, " + "must be a positive 8-bit multiple"; + } + if (td) { + td->PointerPrefAlign = PointerPrefAlignBits / 8; + if (td->PointerPrefAlign == 0) + td->PointerPrefAlign = td->PointerABIAlign; + } break; + } case 'i': case 'v': case 'f': case 'a': case 's': { AlignTypeEnum AlignType; - switch (Specifier[0]) { + char field = Specifier[0]; + switch (field) { default: case 'i': AlignType = INTEGER_ALIGN; break; case 'v': AlignType = VECTOR_ALIGN; break; @@ -198,37 +230,66 @@ void TargetData::init(StringRef Desc) { case 'a': AlignType = AGGREGATE_ALIGN; break; case 's': AlignType = STACK_ALIGN; break; } - unsigned Size = getInt(Specifier.substr(1)); + int Size = getInt(Specifier.substr(1)); + if (Size < 0) { + return std::string("invalid ") + field + "-size field, " + "must be positive"; + } + Split = Token.split(':'); - unsigned ABIAlign = getInt(Split.first) / 8; + int ABIAlignBits = getInt(Split.first); + if (ABIAlignBits < 0 || ABIAlignBits % 8 != 0) { + return std::string("invalid ") + field +"-abi-alignment field, " + "must be a positive 8-bit multiple"; + } + unsigned ABIAlign = ABIAlignBits / 8; Split = Split.second.split(':'); - unsigned PrefAlign = getInt(Split.first) / 8; + + int PrefAlignBits = getInt(Split.first); + if (PrefAlignBits < 0 || PrefAlignBits % 8 != 0) { + return std::string("invalid ") + field +"-preferred-alignment field, " + "must be a positive 8-bit multiple"; + } + unsigned PrefAlign = PrefAlignBits / 8; if (PrefAlign == 0) PrefAlign = ABIAlign; - setAlignment(AlignType, ABIAlign, PrefAlign, Size); + + if (td) + td->setAlignment(AlignType, ABIAlign, PrefAlign, Size); break; } case 'n': // Native integer types. Specifier = Specifier.substr(1); do { - if (unsigned Width = getInt(Specifier)) - LegalIntWidths.push_back(Width); + int Width = getInt(Specifier); + if (Width <= 0) { + return std::string("invalid native integer size \'") + Specifier.str() + + "\', must be a positive integer."; + } + if (td && Width != 0) + td->LegalIntWidths.push_back(Width); Split = Token.split(':'); Specifier = Split.first; Token = Split.second; } while (!Specifier.empty() || !Token.empty()); break; - case 'S': // Stack natural alignment. - StackNaturalAlign = getInt(Specifier.substr(1)); - StackNaturalAlign /= 8; - // FIXME: Should we really be truncating these alingments and - // sizes silently? + case 'S': { // Stack natural alignment. + int StackNaturalAlignBits = getInt(Specifier.substr(1)); + if (StackNaturalAlignBits < 0 || StackNaturalAlignBits % 8 != 0) { + return "invalid natural stack alignment (S-field), " + "must be a positive 8-bit multiple"; + } + if (td) + td->StackNaturalAlign = StackNaturalAlignBits / 8; break; + } default: break; } } + + return ""; } /// Default ctor. @@ -242,7 +303,9 @@ TargetData::TargetData() : ImmutablePass(ID) { TargetData::TargetData(const Module *M) : ImmutablePass(ID) { - init(M->getDataLayout()); + std::string errMsg = parseSpecifier(M->getDataLayout(), this); + assert(errMsg == "" && "Module M has malformed target data layout string."); + (void)errMsg; } void