Re-applying the target data layout verification patch from r142288, plus appropriate CMake dependencies.

Thanks to Raphael Espindola for tracking down the CMake issues.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@142306 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Lang Hames 2011-10-17 23:24:48 +00:00
parent ea46110f57
commit 5fa792e65a
4 changed files with 116 additions and 38 deletions

View File

@ -44,7 +44,7 @@ enum AlignTypeEnum {
AGGREGATE_ALIGN = 'a', ///< Aggregate alignment AGGREGATE_ALIGN = 'a', ///< Aggregate alignment
STACK_ALIGN = 's' ///< Stack objects alignment STACK_ALIGN = 's' ///< Stack objects alignment
}; };
/// Target alignment element. /// Target alignment element.
/// ///
/// Stores the alignment data associated with a given alignment type (pointer, /// Stores the alignment data associated with a given alignment type (pointer,
@ -80,7 +80,7 @@ private:
unsigned StackNaturalAlign; ///< Stack natural alignment unsigned StackNaturalAlign; ///< Stack natural alignment
SmallVector<unsigned char, 8> LegalIntWidths; ///< Legal Integers. SmallVector<unsigned char, 8> LegalIntWidths; ///< Legal Integers.
/// Alignments- Where the primitive type alignment data is stored. /// Alignments- Where the primitive type alignment data is stored.
/// ///
/// @sa init(). /// @sa init().
@ -88,7 +88,7 @@ private:
/// pointers vs. 64-bit pointers by extending TargetAlignment, but for now, /// pointers vs. 64-bit pointers by extending TargetAlignment, but for now,
/// we don't. /// we don't.
SmallVector<TargetAlignElem, 16> Alignments; SmallVector<TargetAlignElem, 16> Alignments;
/// InvalidAlignmentElem - This member is a signal that a requested alignment /// InvalidAlignmentElem - This member is a signal that a requested alignment
/// type and bit width were not found in the SmallVector. /// type and bit width were not found in the SmallVector.
static const TargetAlignElem InvalidAlignmentElem; static const TargetAlignElem InvalidAlignmentElem;
@ -112,19 +112,30 @@ private:
return &align != &InvalidAlignmentElem; return &align != &InvalidAlignmentElem;
} }
/// Initialise a TargetData object with default values, ensure that the
/// target data pass is registered.
void init();
public: public:
/// Default ctor. /// Default ctor.
/// ///
/// @note This has to exist, because this is a pass, but it should never be /// @note This has to exist, because this is a pass, but it should never be
/// used. /// used.
TargetData(); TargetData();
/// Constructs a TargetData from a specification string. See init(). /// Constructs a TargetData from a specification string. See init().
explicit TargetData(StringRef TargetDescription) explicit TargetData(StringRef TargetDescription)
: ImmutablePass(ID) { : 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. /// Initialize target data from properties stored in the module.
explicit TargetData(const Module *M); explicit TargetData(const Module *M);
@ -141,9 +152,6 @@ public:
~TargetData(); // Not virtual, do not subclass this class ~TargetData(); // Not virtual, do not subclass this class
//! Parse a target data layout string and initialize TargetData alignments.
void init(StringRef TargetDescription);
/// Target endianness... /// Target endianness...
bool isLittleEndian() const { return LittleEndian; } bool isLittleEndian() const { return LittleEndian; }
bool isBigEndian() const { return !LittleEndian; } bool isBigEndian() const { return !LittleEndian; }
@ -152,7 +160,7 @@ public:
/// TargetData. This representation is in the same format accepted by the /// TargetData. This representation is in the same format accepted by the
/// string constructor above. /// string constructor above.
std::string getStringRepresentation() const; std::string getStringRepresentation() const;
/// isLegalInteger - This function returns true if the specified type is /// isLegalInteger - This function returns true if the specified type is
/// known to be a native integer type supported by the CPU. For example, /// 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 /// 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 true;
return false; return false;
} }
bool isIllegalInteger(unsigned Width) const { bool isIllegalInteger(unsigned Width) const {
return !isLegalInteger(Width); return !isLegalInteger(Width);
} }
@ -251,11 +259,11 @@ public:
/// getABITypeAlignment - Return the minimum ABI-required alignment for the /// getABITypeAlignment - Return the minimum ABI-required alignment for the
/// specified type. /// specified type.
unsigned getABITypeAlignment(Type *Ty) const; unsigned getABITypeAlignment(Type *Ty) const;
/// getABIIntegerTypeAlignment - Return the minimum ABI-required alignment for /// getABIIntegerTypeAlignment - Return the minimum ABI-required alignment for
/// an integer type of the specified bitwidth. /// an integer type of the specified bitwidth.
unsigned getABIIntegerTypeAlignment(unsigned BitWidth) const; unsigned getABIIntegerTypeAlignment(unsigned BitWidth) const;
/// getCallFrameTypeAlignment - Return the minimum ABI-required alignment /// getCallFrameTypeAlignment - Return the minimum ABI-required alignment
/// for the specified type when it is part of a call frame. /// 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!"); assert((Alignment & (Alignment-1)) == 0 && "Alignment must be power of 2!");
return (Val + (Alignment-1)) & ~UIntTy(Alignment-1); return (Val + (Alignment-1)) & ~UIntTy(Alignment-1);
} }
static char ID; // Pass identification, replacement for typeid static char ID; // Pass identification, replacement for typeid
}; };

View File

@ -8,4 +8,5 @@ add_llvm_library(LLVMAsmParser
add_llvm_library_dependencies(LLVMAsmParser add_llvm_library_dependencies(LLVMAsmParser
LLVMCore LLVMCore
LLVMSupport LLVMSupport
LLVMTarget
) )

View File

@ -24,6 +24,7 @@
#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetData.h"
using namespace llvm; using namespace llvm;
static std::string getTypeString(Type *T) { static std::string getTypeString(Type *T) {
@ -260,9 +261,14 @@ bool LLParser::ParseTargetDefinition() {
return false; return false;
case lltok::kw_datalayout: case lltok::kw_datalayout:
Lex.Lex(); Lex.Lex();
LocTy SpecifierLoc = Lex.getLoc();
if (ParseToken(lltok::equal, "expected '=' after target datalayout") || if (ParseToken(lltok::equal, "expected '=' after target datalayout") ||
ParseStringConstant(Str)) ParseStringConstant(Str))
return true; return true;
std::string errMsg = TargetData::parseSpecifier(Str);
if (errMsg != "") {
return Error(SpecifierLoc, errMsg);
}
M->setDataLayout(Str); M->setDataLayout(Str);
return false; return false;
} }

View File

@ -125,15 +125,15 @@ const TargetAlignElem TargetData::InvalidAlignmentElem =
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
/// getInt - Get an integer ignoring errors. /// getInt - Get an integer ignoring errors.
static unsigned getInt(StringRef R) { static int getInt(StringRef R) {
unsigned Result = 0; int Result = 0;
R.getAsInteger(10, Result); R.getAsInteger(10, Result);
return Result; return Result;
} }
void TargetData::init(StringRef Desc) { void TargetData::init() {
initializeTargetDataPass(*PassRegistry::getPassRegistry()); initializeTargetDataPass(*PassRegistry::getPassRegistry());
LayoutMap = 0; LayoutMap = 0;
LittleEndian = false; LittleEndian = false;
PointerMemSize = 8; PointerMemSize = 8;
@ -152,6 +152,12 @@ void TargetData::init(StringRef Desc) {
setAlignment(VECTOR_ALIGN, 8, 8, 64); // v2i32, v1i64, ... setAlignment(VECTOR_ALIGN, 8, 8, 64); // v2i32, v1i64, ...
setAlignment(VECTOR_ALIGN, 16, 16, 128); // v16i8, v8i16, v4i32, ... setAlignment(VECTOR_ALIGN, 16, 16, 128); // v16i8, v8i16, v4i32, ...
setAlignment(AGGREGATE_ALIGN, 0, 8, 0); // struct setAlignment(AGGREGATE_ALIGN, 0, 8, 0); // struct
}
std::string TargetData::parseSpecifier(StringRef Desc, TargetData *td) {
if (td)
td->init();
while (!Desc.empty()) { while (!Desc.empty()) {
std::pair<StringRef, StringRef> Split = Desc.split('-'); std::pair<StringRef, StringRef> Split = Desc.split('-');
@ -169,28 +175,54 @@ void TargetData::init(StringRef Desc) {
switch (Specifier[0]) { switch (Specifier[0]) {
case 'E': case 'E':
LittleEndian = false; if (td)
td->LittleEndian = false;
break; break;
case 'e': case 'e':
LittleEndian = true; if (td)
td->LittleEndian = true;
break; break;
case 'p': case 'p': {
// Pointer size.
Split = Token.split(':'); 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(':'); 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(':'); Split = Split.second.split(':');
PointerPrefAlign = getInt(Split.first) / 8; int PointerPrefAlignBits = getInt(Split.first);
if (PointerPrefAlign == 0) if (PointerPrefAlignBits < 0 || PointerPrefAlignBits % 8 != 0) {
PointerPrefAlign = PointerABIAlign; 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; break;
}
case 'i': case 'i':
case 'v': case 'v':
case 'f': case 'f':
case 'a': case 'a':
case 's': { case 's': {
AlignTypeEnum AlignType; AlignTypeEnum AlignType;
switch (Specifier[0]) { char field = Specifier[0];
switch (field) {
default: default:
case 'i': AlignType = INTEGER_ALIGN; break; case 'i': AlignType = INTEGER_ALIGN; break;
case 'v': AlignType = VECTOR_ALIGN; break; case 'v': AlignType = VECTOR_ALIGN; break;
@ -198,37 +230,66 @@ void TargetData::init(StringRef Desc) {
case 'a': AlignType = AGGREGATE_ALIGN; break; case 'a': AlignType = AGGREGATE_ALIGN; break;
case 's': AlignType = STACK_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(':'); 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(':'); 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) if (PrefAlign == 0)
PrefAlign = ABIAlign; PrefAlign = ABIAlign;
setAlignment(AlignType, ABIAlign, PrefAlign, Size);
if (td)
td->setAlignment(AlignType, ABIAlign, PrefAlign, Size);
break; break;
} }
case 'n': // Native integer types. case 'n': // Native integer types.
Specifier = Specifier.substr(1); Specifier = Specifier.substr(1);
do { do {
if (unsigned Width = getInt(Specifier)) int Width = getInt(Specifier);
LegalIntWidths.push_back(Width); 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(':'); Split = Token.split(':');
Specifier = Split.first; Specifier = Split.first;
Token = Split.second; Token = Split.second;
} while (!Specifier.empty() || !Token.empty()); } while (!Specifier.empty() || !Token.empty());
break; break;
case 'S': // Stack natural alignment. case 'S': { // Stack natural alignment.
StackNaturalAlign = getInt(Specifier.substr(1)); int StackNaturalAlignBits = getInt(Specifier.substr(1));
StackNaturalAlign /= 8; if (StackNaturalAlignBits < 0 || StackNaturalAlignBits % 8 != 0) {
// FIXME: Should we really be truncating these alingments and return "invalid natural stack alignment (S-field), "
// sizes silently? "must be a positive 8-bit multiple";
}
if (td)
td->StackNaturalAlign = StackNaturalAlignBits / 8;
break; break;
}
default: default:
break; break;
} }
} }
return "";
} }
/// Default ctor. /// Default ctor.
@ -242,7 +303,9 @@ TargetData::TargetData() : ImmutablePass(ID) {
TargetData::TargetData(const Module *M) TargetData::TargetData(const Module *M)
: ImmutablePass(ID) { : 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 void