[llvm] [DataLayout] Refactor `parseSpecification` (PR #104545)
Sergei Barannikov via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 15 21:39:00 PDT 2024
https://github.com/s-barannikov updated https://github.com/llvm/llvm-project/pull/104545
>From ef37d9c5cf35f6610b3d3eb1b28f8990ac23381a Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Thu, 15 Aug 2024 18:30:16 +0300
Subject: [PATCH] [DataLayout] Refactor `parseSpecification`
---
llvm/include/llvm/IR/DataLayout.h | 33 +-
llvm/lib/IR/DataLayout.cpp | 531 +++++++++---------
llvm/test/Assembler/getInt.ll | 3 -
.../Assembler/invalid-datalayout-override.ll | 2 +-
.../function-default-address-spaces.ll | 2 +-
.../test/Bitcode/invalid-functionptr-align.ll | 5 -
...ptr-align.ll.bc => invalid-stack-align.bc} | Bin
llvm/test/Bitcode/invalid-stack-align.ll.bc | 5 +
llvm/test/Transforms/InstCombine/crash.ll | 2 +-
llvm/test/Transforms/InstCombine/phi.ll | 2 +-
llvm/unittests/IR/DataLayoutTest.cpp | 110 ++--
11 files changed, 338 insertions(+), 357 deletions(-)
delete mode 100644 llvm/test/Assembler/getInt.ll
delete mode 100644 llvm/test/Bitcode/invalid-functionptr-align.ll
rename llvm/test/Bitcode/{invalid-functionptr-align.ll.bc => invalid-stack-align.bc} (100%)
create mode 100644 llvm/test/Bitcode/invalid-stack-align.ll.bc
diff --git a/llvm/include/llvm/IR/DataLayout.h b/llvm/include/llvm/IR/DataLayout.h
index 228b723ee663ff..16defd48ec8ff5 100644
--- a/llvm/include/llvm/IR/DataLayout.h
+++ b/llvm/include/llvm/IR/DataLayout.h
@@ -115,14 +115,6 @@ class DataLayout {
// FIXME: `unsigned char` truncates the value parsed by `parseSpecifier`.
SmallVector<unsigned char, 8> LegalIntWidths;
- /// Type specifier used by some internal functions.
- enum class TypeSpecifier {
- Integer = 'i',
- Float = 'f',
- Vector = 'v',
- Aggregate = 'a'
- };
-
/// Primitive type specifications. Sorted and uniqued by type bit width.
SmallVector<PrimitiveSpec, 6> IntSpecs;
SmallVector<PrimitiveSpec, 4> FloatSpecs;
@@ -145,19 +137,17 @@ class DataLayout {
/// well-defined bitwise representation.
SmallVector<unsigned, 8> NonIntegralAddressSpaces;
- /// Attempts to set the specification for the given type.
- /// Returns an error description on failure.
- Error setPrimitiveSpec(TypeSpecifier Specifier, uint32_t BitWidth,
- Align ABIAlign, Align PrefAlign);
+ /// Sets or updates the specification for the given primitive type.
+ void setPrimitiveSpec(char Specifier, uint32_t BitWidth, Align ABIAlign,
+ Align PrefAlign);
/// Searches for a pointer specification that matches the given address space.
/// Returns the default address space specification if not found.
const PointerSpec &getPointerSpec(uint32_t AddrSpace) const;
- /// Attempts to set the specification for pointer in the given address space.
- /// Returns an error description on failure.
- Error setPointerSpec(uint32_t AddrSpace, uint32_t BitWidth, Align ABIAlign,
- Align PrefAlign, uint32_t IndexBitWidth);
+ /// Sets or updates the specification for pointer in the given address space.
+ void setPointerSpec(uint32_t AddrSpace, uint32_t BitWidth, Align ABIAlign,
+ Align PrefAlign, uint32_t IndexBitWidth);
/// Internal helper to get alignment for integer of given bitwidth.
Align getIntegerAlignment(uint32_t BitWidth, bool abi_or_pref) const;
@@ -165,8 +155,17 @@ class DataLayout {
/// Internal helper method that returns requested alignment for type.
Align getAlignment(Type *Ty, bool abi_or_pref) const;
+ /// Attempts to parse primitive specification ('i', 'f', or 'v').
+ Error parsePrimitiveSpec(StringRef SpecStr);
+
+ /// Attempts to parse aggregate specification ('a').
+ Error parseAggregateSpec(StringRef SpecStr);
+
+ /// Attempts to parse pointer specification ('p').
+ Error parsePointerSpec(StringRef SpecStr);
+
/// Attempts to parse a single specification.
- Error parseSpecification(StringRef Specification);
+ Error parseSpecification(StringRef SpecStr);
/// Attempts to parse a data layout string.
Error parseLayoutString(StringRef LayoutString);
diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp
index 24c29458abfa81..10ed0558ecc25a 100644
--- a/llvm/lib/IR/DataLayout.cpp
+++ b/llvm/lib/IR/DataLayout.cpp
@@ -268,251 +268,272 @@ Expected<DataLayout> DataLayout::parse(StringRef LayoutString) {
return Layout;
}
-static Error reportError(const Twine &Message) {
- return createStringError(inconvertibleErrorCode(), Message);
-}
-
-/// Checked version of split, to ensure mandatory subparts.
-static Error split(StringRef Str, char Separator,
- std::pair<StringRef, StringRef> &Split) {
- assert(!Str.empty() && "parse error, string can't be empty here");
- Split = Str.split(Separator);
- if (Split.second.empty() && Split.first != Str)
- return reportError("Trailing separator in datalayout string");
- if (!Split.second.empty() && Split.first.empty())
- return reportError("Expected token before separator in datalayout string");
+/// Attempts to parse an address space component of a specification,
+/// commonly referred to as <n> or <address space>.
+static Error parseAddrSpace(StringRef Str, unsigned &AddrSpace,
+ StringRef Name) {
+ if (Str.empty())
+ return createStringError(Name + " is required");
+
+ if (!to_integer(Str, AddrSpace, 10) || !isUInt<24>(AddrSpace))
+ return createStringError(Name + " must be a 24-bit integer");
+
return Error::success();
}
-/// Get an unsigned integer, including error checks.
-template <typename IntTy> static Error getInt(StringRef R, IntTy &Result) {
- bool error = R.getAsInteger(10, Result); (void)error;
- if (error)
- return reportError("not a number, or does not fit in an unsigned int");
+/// Attempts to parse a size component of a specification,
+/// commonly referred to as <size>.
+static Error parseSize(StringRef Str, unsigned &BitWidth, StringRef Name) {
+ if (Str.empty())
+ return createStringError(Name + " is required");
+
+ if (!to_integer(Str, BitWidth, 10) || BitWidth == 0 || !isUInt<24>(BitWidth))
+ return createStringError(Name + " must be a non-zero 24-bit integer");
+
return Error::success();
}
-/// Get an unsigned integer representing the number of bits and convert it into
-/// bytes. Error out of not a byte width multiple.
-template <typename IntTy>
-static Error getIntInBytes(StringRef R, IntTy &Result) {
- if (Error Err = getInt<IntTy>(R, Result))
- return Err;
- if (Result % 8)
- return reportError("number of bits must be a byte width multiple");
- Result /= 8;
+/// Attempts to parse an alignment component of a specification,
+/// commonly referred to as <abi> or <pref>.
+///
+/// On success, returns the value converted to byte amount in \p Alignment.
+/// If the value is zero and \p AllowZero is true, \p Alignment is set to one.
+///
+/// Return an error in a number of cases:
+/// - \p Str is empty or contains characters other than decimal digits;
+/// - the value is zero and \p AllowZero is false;
+/// - the value is too large;
+/// - the value is not a multiple of the byte width;
+/// - the value converted to byte amount is not not a power of two.
+///
+/// \p Name should be the name of the alignment component as specified
+/// in LangRef, it is used in diagnostic messages.
+static Error parseAlignment(StringRef Str, Align &Alignment, StringRef Name,
+ bool AllowZero = false) {
+ if (Str.empty())
+ return createStringError(Name + " is required");
+
+ unsigned Value;
+ if (!to_integer(Str, Value, 10) || !isUInt<16>(Value))
+ return createStringError(Name + " must be a 16-bit integer");
+
+ if (Value == 0) {
+ if (!AllowZero)
+ return createStringError(Name + " must be non-zero");
+ Alignment = Align(1);
+ return Error::success();
+ }
+
+ constexpr unsigned ByteWidth = 8;
+ if (Value % ByteWidth || !isPowerOf2_32(Value / ByteWidth))
+ return createStringError(Name +
+ " must be a power of two times the byte width");
+
+ Alignment = Align(Value / ByteWidth);
return Error::success();
}
-static Error getAddrSpace(StringRef R, unsigned &AddrSpace) {
- if (Error Err = getInt(R, AddrSpace))
+static Error createSpecFormatError(Twine Format) {
+ return createStringError("malformed specification, must be of the form \"" +
+ Format + "\"");
+}
+
+Error DataLayout::parsePrimitiveSpec(StringRef SpecStr) {
+ // [ifv]<size>:<abi>[:<pref>]
+ SmallVector<StringRef, 3> Components;
+ char Specifier = SpecStr.front();
+ assert(Specifier == 'i' || Specifier == 'f' || Specifier == 'v');
+ SpecStr.drop_front().split(Components, ':');
+
+ if (Components.size() < 2 || Components.size() > 3)
+ return createSpecFormatError(Twine(Specifier) + "<size>:<abi>[:<pref>]");
+
+ // Size. Required, cannot be zero.
+ unsigned BitWidth;
+ if (Error Err = parseSize(Components[0], BitWidth, "<size>"))
+ return Err;
+
+ // ABI alignment. Required, cannot be zero.
+ Align ABIAlign;
+ if (Error Err = parseAlignment(Components[1], ABIAlign, "<abi>"))
return Err;
- if (!isUInt<24>(AddrSpace))
- return reportError("Invalid address space, must be a 24-bit integer");
+
+ constexpr unsigned ByteWidth = 8;
+ if (Specifier == 'i' && BitWidth == ByteWidth && ABIAlign != 1)
+ return createStringError("<abi> must be exactly " + Twine(ByteWidth));
+
+ // Preferred alignment. Optional, defaults to the ABI alignment.
+ // Can be zero, meaning use ABI alignment.
+ Align PrefAlign = ABIAlign;
+ if (Components.size() > 2)
+ if (Error Err = parseAlignment(Components[2], PrefAlign, "<pref>",
+ /*AllowZero=*/true))
+ return Err;
+
+ if (PrefAlign < ABIAlign)
+ return createStringError("<pref> cannot be less than <abi>");
+
+ setPrimitiveSpec(Specifier, BitWidth, ABIAlign, PrefAlign);
return Error::success();
}
-Error DataLayout::parseSpecification(StringRef Spec) {
- // Split at ':'.
- std::pair<StringRef, StringRef> Split;
- if (Error Err = ::split(Spec, ':', Split))
+Error DataLayout::parseAggregateSpec(StringRef SpecStr) {
+ // a<size>:<abi>[:<pref>]
+ SmallVector<StringRef, 3> Components;
+ assert(SpecStr.front() == 'a');
+ SpecStr.drop_front().split(Components, ':');
+
+ if (Components.size() < 2 || Components.size() > 3)
+ return createSpecFormatError("a:<abi>[:<pref>]");
+
+ // According to LangRef, <size> component must be absent altogether.
+ // For backward compatibility, allow it to be specified, but require
+ // it to be literal "0".
+ if (!Components[0].empty() && Components[0] != "0")
+ return createStringError("<size> is not applicable to aggregates");
+
+ // ABI alignment. Required.
+ // Can be zero, meaning use one byte alignment.
+ Align ABIAlign;
+ if (Error Err =
+ parseAlignment(Components[1], ABIAlign, "<abi>", /*AllowZero=*/true))
return Err;
- // Aliases used below.
- StringRef &Tok = Split.first; // Current token.
- StringRef &Rest = Split.second; // The rest of the string.
+ // Preferred alignment. Optional, defaults to the ABI alignment.
+ // Can be zero, meaning use ABI alignment.
+ Align PrefAlign = ABIAlign;
+ if (Components.size() > 2)
+ if (Error Err = parseAlignment(Components[2], PrefAlign, "<pref>",
+ /*AllowZero=*/true))
+ return Err;
- if (Tok == "ni") {
- do {
- if (Error Err = ::split(Rest, ':', Split))
- return Err;
- Rest = Split.second;
- unsigned AS;
- if (Error Err = getInt(Split.first, AS))
- return Err;
- if (AS == 0)
- return reportError("Address space 0 can never be non-integral");
- NonIntegralAddressSpaces.push_back(AS);
- } while (!Rest.empty());
+ if (PrefAlign < ABIAlign)
+ return createStringError("<pref> cannot be less than <abi>");
- return Error::success();
- }
+ StructABIAlignment = ABIAlign;
+ StructPrefAlignment = PrefAlign;
+ return Error::success();
+}
- char SpecifierChar = Tok.front();
- Tok = Tok.substr(1);
+Error DataLayout::parsePointerSpec(StringRef SpecStr) {
+ // p[n]:<size>:<abi>[:<pref>][:<idx>]
+ SmallVector<StringRef, 5> Components;
+ assert(SpecStr.front() == 'p');
+ SpecStr.drop_front().split(Components, ':');
- switch (SpecifierChar) {
- case 's':
- // Deprecated, but ignoring here to preserve loading older textual llvm
- // ASM file
- break;
- case 'E':
- BigEndian = true;
- break;
- case 'e':
- BigEndian = false;
- break;
- case 'p': {
- // Address space.
- unsigned AddrSpace = 0;
- if (!Tok.empty())
- if (Error Err = getInt(Tok, AddrSpace))
- return Err;
- if (!isUInt<24>(AddrSpace))
- return reportError("Invalid address space, must be a 24-bit integer");
-
- // Size.
- if (Rest.empty())
- return reportError(
- "Missing size specification for pointer in datalayout string");
- if (Error Err = ::split(Rest, ':', Split))
- return Err;
- unsigned PointerMemSize;
- if (Error Err = getInt(Tok, PointerMemSize))
- return Err;
- if (!PointerMemSize)
- return reportError("Invalid pointer size of 0 bytes");
-
- // ABI alignment.
- if (Rest.empty())
- return reportError(
- "Missing alignment specification for pointer in datalayout string");
- if (Error Err = ::split(Rest, ':', Split))
+ if (Components.size() < 3 || Components.size() > 5)
+ return createSpecFormatError("p[n]:<size>:<abi>[:<pref>][:<idx>]");
+
+ // Address space. Optional, defaults to 0.
+ unsigned AddrSpace = 0;
+ if (!Components[0].empty())
+ if (Error Err = parseAddrSpace(Components[0], AddrSpace, "<n>"))
return Err;
- unsigned PointerABIAlign;
- if (Error Err = getIntInBytes(Tok, PointerABIAlign))
+
+ // Size. Required, cannot be zero.
+ unsigned BitWidth;
+ if (Error Err = parseSize(Components[1], BitWidth, "<size>"))
+ return Err;
+
+ // ABI alignment. Required, cannot be zero.
+ Align ABIAlign;
+ if (Error Err = parseAlignment(Components[2], ABIAlign, "<abi>"))
+ return Err;
+
+ // Preferred alignment. Optional, defaults to the ABI alignment.
+ // Cannot be zero.
+ Align PrefAlign = ABIAlign;
+ if (Components.size() > 3)
+ if (Error Err = parseAlignment(Components[3], PrefAlign, "<pref>"))
return Err;
- if (!isPowerOf2_64(PointerABIAlign))
- return reportError("Pointer ABI alignment must be a power of 2");
- // Size of index used in GEP for address calculation.
- // The parameter is optional. By default it is equal to size of pointer.
- unsigned IndexSize = PointerMemSize;
+ if (PrefAlign < ABIAlign)
+ return createStringError("<pref> cannot be less than <abi>");
- // Preferred alignment.
- unsigned PointerPrefAlign = PointerABIAlign;
- if (!Rest.empty()) {
- if (Error Err = ::split(Rest, ':', Split))
- return Err;
- if (Error Err = getIntInBytes(Tok, PointerPrefAlign))
- return Err;
- if (!isPowerOf2_64(PointerPrefAlign))
- return reportError("Pointer preferred alignment must be a power of 2");
-
- // Now read the index. It is the second optional parameter here.
- if (!Rest.empty()) {
- if (Error Err = ::split(Rest, ':', Split))
- return Err;
- if (Error Err = getInt(Tok, IndexSize))
- return Err;
- if (!IndexSize)
- return reportError("Invalid index size of 0 bytes");
- }
- }
- if (Error Err = setPointerSpec(AddrSpace, PointerMemSize,
- assumeAligned(PointerABIAlign),
- assumeAligned(PointerPrefAlign), IndexSize))
+ // Index size. Optional, defaults to pointer size. Cannot be zero.
+ unsigned IndexBitWidth = BitWidth;
+ if (Components.size() > 4)
+ if (Error Err = parseSize(Components[4], IndexBitWidth, "<idx>"))
return Err;
- break;
- }
- case 'i':
- case 'v':
- case 'f':
- case 'a': {
- TypeSpecifier Specifier;
- switch (SpecifierChar) {
- default:
- llvm_unreachable("Unexpected specifier!");
- case 'i':
- Specifier = TypeSpecifier::Integer;
- break;
- case 'v':
- Specifier = TypeSpecifier::Vector;
- break;
- case 'f':
- Specifier = TypeSpecifier::Float;
- break;
- case 'a':
- Specifier = TypeSpecifier::Aggregate;
- break;
- }
- // Bit size.
- unsigned Size = 0;
- if (!Tok.empty())
- if (Error Err = getInt(Tok, Size))
- return Err;
+ if (IndexBitWidth > BitWidth)
+ return createStringError("index size cannot be larger than pointer size");
+
+ setPointerSpec(AddrSpace, BitWidth, ABIAlign, PrefAlign, IndexBitWidth);
+ return Error::success();
+}
- if (Specifier == TypeSpecifier::Aggregate && Size != 0)
- return reportError("Sized aggregate specification in datalayout string");
+Error DataLayout::parseSpecification(StringRef SpecStr) {
+ // The "ni" specifier is the only two-character specifier. Handle it first.
+ if (SpecStr.starts_with("ni")) {
+ // ni:<address space>[:<address space>]...
+ StringRef Rest = SpecStr.drop_front(2);
- // ABI alignment.
- if (Rest.empty())
- return reportError(
- "Missing alignment specification in datalayout string");
- if (Error Err = ::split(Rest, ':', Split))
- return Err;
- unsigned ABIAlign;
- if (Error Err = getIntInBytes(Tok, ABIAlign))
- return Err;
- if (Specifier != TypeSpecifier::Aggregate && !ABIAlign)
- return reportError(
- "ABI alignment specification must be >0 for non-aggregate types");
-
- if (!isUInt<16>(ABIAlign))
- return reportError("Invalid ABI alignment, must be a 16bit integer");
- if (ABIAlign != 0 && !isPowerOf2_64(ABIAlign))
- return reportError("Invalid ABI alignment, must be a power of 2");
- if (Specifier == TypeSpecifier::Integer && Size == 8 && ABIAlign != 1)
- return reportError("Invalid ABI alignment, i8 must be naturally aligned");
-
- // Preferred alignment.
- unsigned PrefAlign = ABIAlign;
- if (!Rest.empty()) {
- if (Error Err = ::split(Rest, ':', Split))
- return Err;
- if (Error Err = getIntInBytes(Tok, PrefAlign))
+ // Drop the first ':', then split the rest of the string the usual way.
+ if (!Rest.consume_front(":"))
+ return createSpecFormatError("ni:<address space>[:<address space>]...");
+
+ for (StringRef AddrSpaceStr : split(Rest, ':')) {
+ unsigned AddrSpace;
+ if (Error Err =
+ parseAddrSpace(AddrSpaceStr, AddrSpace, "<address space>"))
return Err;
+ if (AddrSpace == 0)
+ return createStringError("address space 0 cannot be non-integral");
+ NonIntegralAddressSpaces.push_back(AddrSpace);
}
+ return Error::success();
+ }
- if (!isUInt<16>(PrefAlign))
- return reportError(
- "Invalid preferred alignment, must be a 16bit integer");
- if (PrefAlign != 0 && !isPowerOf2_64(PrefAlign))
- return reportError("Invalid preferred alignment, must be a power of 2");
+ // The rest of the specifiers are single-character.
+ assert(!SpecStr.empty() && "Empty specification is handled by the caller");
+ char Specifier = SpecStr.front();
- if (Error Err = setPrimitiveSpec(Specifier, Size, assumeAligned(ABIAlign),
- assumeAligned(PrefAlign)))
- return Err;
+ if (Specifier == 'i' || Specifier == 'f' || Specifier == 'v')
+ return parsePrimitiveSpec(SpecStr);
+
+ if (Specifier == 'a')
+ return parseAggregateSpec(SpecStr);
+ if (Specifier == 'p')
+ return parsePointerSpec(SpecStr);
+
+ StringRef Rest = SpecStr.drop_front();
+ switch (Specifier) {
+ case 's':
+ // Deprecated, but ignoring here to preserve loading older textual llvm
+ // ASM file
+ break;
+ case 'e':
+ case 'E':
+ BigEndian = Specifier == 'E';
+ if (!Rest.empty())
+ return createSpecFormatError(Twine(Specifier));
break;
- }
case 'n': // Native integer types.
- while (true) {
- unsigned Width;
- if (Error Err = getInt(Tok, Width))
- return Err;
- if (Width == 0)
- return reportError(
- "Zero width native integer type in datalayout string");
- LegalIntWidths.push_back(Width);
- if (Rest.empty())
- break;
- if (Error Err = ::split(Rest, ':', Split))
+ // n<size>[:<size>]...
+ for (StringRef Str : split(Rest, ':')) {
+ unsigned BitWidth;
+ if (Error Err = parseSize(Str, BitWidth, "<size>"))
return Err;
+ LegalIntWidths.push_back(BitWidth);
}
break;
case 'S': { // Stack natural alignment.
- uint64_t Alignment;
- if (Error Err = getIntInBytes(Tok, Alignment))
+ // S<size>
+ Align Alignment;
+ if (Error Err = parseAlignment(Rest, Alignment, "<size>",
+ /*AllowZero=*/true))
return Err;
- if (Alignment != 0 && !llvm::isPowerOf2_64(Alignment))
- return reportError("Alignment is neither 0 nor a power of 2");
- StackNaturalAlign = MaybeAlign(Alignment);
+ StackNaturalAlign = Alignment;
break;
}
case 'F': {
- switch (Tok.front()) {
+ // F<type><abi>
+ // FIXME: Bounds checking.
+ char Type = Rest.front();
+ Rest = Rest.drop_front();
+ switch (Type) {
case 'i':
TheFunctionPtrAlignType = FunctionPtrAlignType::Independent;
break;
@@ -520,44 +541,40 @@ Error DataLayout::parseSpecification(StringRef Spec) {
TheFunctionPtrAlignType = FunctionPtrAlignType::MultipleOfFunctionAlign;
break;
default:
- return reportError("Unknown function pointer alignment type in "
- "datalayout string");
+ return createStringError("unknown function pointer alignment type '" +
+ Twine(Type) + "'");
}
- Tok = Tok.substr(1);
- uint64_t Alignment;
- if (Error Err = getIntInBytes(Tok, Alignment))
+ Align Alignment;
+ if (Error Err = parseAlignment(Rest, Alignment, "<abi>",
+ /*AllowZero=*/true))
return Err;
- if (Alignment != 0 && !llvm::isPowerOf2_64(Alignment))
- return reportError("Alignment is neither 0 nor a power of 2");
- FunctionPtrAlign = MaybeAlign(Alignment);
+ FunctionPtrAlign = Alignment;
break;
}
- case 'P': { // Function address space.
- if (Error Err = getAddrSpace(Tok, ProgramAddrSpace))
+ case 'P':
+ // P<address space>
+ if (Error Err = parseAddrSpace(Rest, ProgramAddrSpace, "<address space>"))
return Err;
break;
- }
- case 'A': { // Default stack/alloca address space.
- if (Error Err = getAddrSpace(Tok, AllocaAddrSpace))
+ case 'A':
+ // A<address space>
+ if (Error Err = parseAddrSpace(Rest, AllocaAddrSpace, "<address space>"))
return Err;
break;
- }
- case 'G': { // Default address space for global variables.
- if (Error Err = getAddrSpace(Tok, DefaultGlobalsAddrSpace))
+ case 'G':
+ // G<address space>
+ if (Error Err =
+ parseAddrSpace(Rest, DefaultGlobalsAddrSpace, "<address space>"))
return Err;
break;
- }
- case 'm':
- if (!Tok.empty())
- return reportError("Unexpected trailing characters after mangling "
- "specifier in datalayout string");
- if (Rest.empty())
- return reportError("Expected mangling specifier in datalayout string");
+ case 'm': {
+ if (!Rest.consume_front(":") || Rest.empty())
+ return createSpecFormatError("m:<mangling>");
if (Rest.size() > 1)
- return reportError("Unknown mangling specifier in datalayout string");
+ return createStringError("unknown mangling specifier");
switch (Rest[0]) {
default:
- return reportError("Unknown mangling in datalayout string");
+ return createStringError("unknown mangling specifier");
case 'e':
ManglingMode = MM_ELF;
break;
@@ -581,8 +598,9 @@ Error DataLayout::parseSpecification(StringRef Spec) {
break;
}
break;
+ }
default:
- return reportError("Unknown specifier in datalayout string");
+ return createStringError("unknown specifier '" + Twine(Specifier) + "'");
}
return Error::success();
@@ -606,46 +624,32 @@ Error DataLayout::parseLayoutString(StringRef LayoutString) {
return Error::success();
}
-Error DataLayout::setPrimitiveSpec(TypeSpecifier Specifier, uint32_t BitWidth,
- Align ABIAlign, Align PrefAlign) {
- // AlignmentsTy::ABIAlign and AlignmentsTy::PrefAlign were once stored as
- // uint16_t, it is unclear if there are requirements for alignment to be less
- // than 2^16 other than storage. In the meantime we leave the restriction as
- // an assert. See D67400 for context.
- assert(Log2(ABIAlign) < 16 && Log2(PrefAlign) < 16 && "Alignment too big");
- if (!isUInt<24>(BitWidth))
- return reportError("Invalid bit width, must be a 24-bit integer");
- if (PrefAlign < ABIAlign)
- return reportError(
- "Preferred alignment cannot be less than the ABI alignment");
-
+void DataLayout::setPrimitiveSpec(char Specifier, uint32_t BitWidth,
+ Align ABIAlign, Align PrefAlign) {
SmallVectorImpl<PrimitiveSpec> *Specs;
switch (Specifier) {
- case TypeSpecifier::Aggregate:
- StructABIAlignment = ABIAlign;
- StructPrefAlignment = PrefAlign;
- return Error::success();
- case TypeSpecifier::Integer:
+ default:
+ llvm_unreachable("Unexpected specifier");
+ case 'i':
Specs = &IntSpecs;
break;
- case TypeSpecifier::Float:
+ case 'f':
Specs = &FloatSpecs;
break;
- case TypeSpecifier::Vector:
+ case 'v':
Specs = &VectorSpecs;
break;
}
auto I = lower_bound(*Specs, BitWidth, LessPrimitiveBitWidth());
if (I != Specs->end() && I->BitWidth == BitWidth) {
- // Update the abi, preferred alignments.
+ // Update existing specification.
I->ABIAlign = ABIAlign;
I->PrefAlign = PrefAlign;
} else {
- // Insert before I to keep the vector sorted.
+ // Insert a new specification before I to keep the vector sorted.
Specs->insert(I, PrimitiveSpec{BitWidth, ABIAlign, PrefAlign});
}
- return Error::success();
}
const DataLayout::PointerSpec &
@@ -660,26 +664,21 @@ DataLayout::getPointerSpec(uint32_t AddrSpace) const {
return PointerSpecs[0];
}
-Error DataLayout::setPointerSpec(uint32_t AddrSpace, uint32_t BitWidth,
- Align ABIAlign, Align PrefAlign,
- uint32_t IndexBitWidth) {
- if (PrefAlign < ABIAlign)
- return reportError(
- "Preferred alignment cannot be less than the ABI alignment");
- if (IndexBitWidth > BitWidth)
- return reportError("Index width cannot be larger than pointer width");
-
+void DataLayout::setPointerSpec(uint32_t AddrSpace, uint32_t BitWidth,
+ Align ABIAlign, Align PrefAlign,
+ uint32_t IndexBitWidth) {
auto I = lower_bound(PointerSpecs, AddrSpace, LessPointerAddrSpace());
- if (I == PointerSpecs.end() || I->AddrSpace != AddrSpace) {
- PointerSpecs.insert(I, PointerSpec{AddrSpace, BitWidth, ABIAlign, PrefAlign,
- IndexBitWidth});
- } else {
+ if (I != PointerSpecs.end() && I->AddrSpace == AddrSpace) {
+ // Update existing specification.
I->BitWidth = BitWidth;
I->ABIAlign = ABIAlign;
I->PrefAlign = PrefAlign;
I->IndexBitWidth = IndexBitWidth;
+ } else {
+ // Insert a new specification before I to keep the vector sorted.
+ PointerSpecs.insert(I, PointerSpec{AddrSpace, BitWidth, ABIAlign, PrefAlign,
+ IndexBitWidth});
}
- return Error::success();
}
Align DataLayout::getIntegerAlignment(uint32_t BitWidth,
diff --git a/llvm/test/Assembler/getInt.ll b/llvm/test/Assembler/getInt.ll
deleted file mode 100644
index 8e2537ae6cf1d8..00000000000000
--- a/llvm/test/Assembler/getInt.ll
+++ /dev/null
@@ -1,3 +0,0 @@
-; RUN: not opt < %s 2>&1 | grep 'not a number, or does not fit in an unsigned int'
-
-target datalayout = "p:4294967296:64:64"
diff --git a/llvm/test/Assembler/invalid-datalayout-override.ll b/llvm/test/Assembler/invalid-datalayout-override.ll
index f62777c6c53287..fc623c62d6501c 100644
--- a/llvm/test/Assembler/invalid-datalayout-override.ll
+++ b/llvm/test/Assembler/invalid-datalayout-override.ll
@@ -4,4 +4,4 @@
; RUN: llvm-as -data-layout "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" < %s
target datalayout = "A16777216"
-; CHECK: Invalid address space, must be a 24-bit integer
+; CHECK: <address space> must be a 24-bit integer
diff --git a/llvm/test/Bitcode/function-default-address-spaces.ll b/llvm/test/Bitcode/function-default-address-spaces.ll
index 3aae5db863b88a..c93a0263afcbfd 100644
--- a/llvm/test/Bitcode/function-default-address-spaces.ll
+++ b/llvm/test/Bitcode/function-default-address-spaces.ll
@@ -1,7 +1,7 @@
; RUN: llvm-as %s -o - | llvm-dis - | FileCheck %s -check-prefixes CHECK,PROG-AS0
; RUN: llvm-as -data-layout "P200" %s -o - | llvm-dis | FileCheck %s -check-prefixes CHECK,PROG-AS200
; RUN: not llvm-as -data-layout "P123456789" %s -o /dev/null 2>&1 | FileCheck %s -check-prefix BAD-DATALAYOUT
-; BAD-DATALAYOUT: error: Invalid address space, must be a 24-bit integer
+; BAD-DATALAYOUT: error: <address space> must be a 24-bit integer
; PROG-AS0-NOT: target datalayout
; PROG-AS200: target datalayout = "P200"
diff --git a/llvm/test/Bitcode/invalid-functionptr-align.ll b/llvm/test/Bitcode/invalid-functionptr-align.ll
deleted file mode 100644
index 8b446d371f6fde..00000000000000
--- a/llvm/test/Bitcode/invalid-functionptr-align.ll
+++ /dev/null
@@ -1,5 +0,0 @@
-; Bitcode with invalid function pointer alignment.
-
-; RUN: not llvm-dis %s.bc -o - 2>&1 | FileCheck %s
-
-CHECK: error: Alignment is neither 0 nor a power of 2
diff --git a/llvm/test/Bitcode/invalid-functionptr-align.ll.bc b/llvm/test/Bitcode/invalid-stack-align.bc
similarity index 100%
rename from llvm/test/Bitcode/invalid-functionptr-align.ll.bc
rename to llvm/test/Bitcode/invalid-stack-align.bc
diff --git a/llvm/test/Bitcode/invalid-stack-align.ll.bc b/llvm/test/Bitcode/invalid-stack-align.ll.bc
new file mode 100644
index 00000000000000..d499d707e3514c
--- /dev/null
+++ b/llvm/test/Bitcode/invalid-stack-align.ll.bc
@@ -0,0 +1,5 @@
+; Bitcode with invalid natural stack alignment.
+
+; RUN: not llvm-dis %s.bc -o - 2>&1 | FileCheck %s
+
+CHECK: error: <size> must be a power of two times the byte width
diff --git a/llvm/test/Transforms/InstCombine/crash.ll b/llvm/test/Transforms/InstCombine/crash.ll
index 5f86069ef73680..9b37d6943b9e52 100644
--- a/llvm/test/Transforms/InstCombine/crash.ll
+++ b/llvm/test/Transforms/InstCombine/crash.ll
@@ -1,5 +1,5 @@
; RUN: opt < %s -passes=instcombine -S
-target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128:n8:16:32"
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32"
target triple = "i386-apple-darwin10.0"
define i32 @test0(i8 %tmp2) ssp {
diff --git a/llvm/test/Transforms/InstCombine/phi.ll b/llvm/test/Transforms/InstCombine/phi.ll
index b12982dd27e404..2673b1d74bb6fb 100644
--- a/llvm/test/Transforms/InstCombine/phi.ll
+++ b/llvm/test/Transforms/InstCombine/phi.ll
@@ -1,7 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
-target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128:n8:16:32:64"
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
define i32 @test1(i32 %A, i1 %b) {
; CHECK-LABEL: @test1(
diff --git a/llvm/unittests/IR/DataLayoutTest.cpp b/llvm/unittests/IR/DataLayoutTest.cpp
index f5c930ebdbb9c4..32c2568ba7f677 100644
--- a/llvm/unittests/IR/DataLayoutTest.cpp
+++ b/llvm/unittests/IR/DataLayoutTest.cpp
@@ -21,107 +21,93 @@ namespace {
// TODO: Split into multiple TESTs.
TEST(DataLayoutTest, ParseErrors) {
- EXPECT_THAT_EXPECTED(
- DataLayout::parse("^"),
- FailedWithMessage("Unknown specifier in datalayout string"));
- EXPECT_THAT_EXPECTED(
- DataLayout::parse("m:v"),
- FailedWithMessage("Unknown mangling in datalayout string"));
+ EXPECT_THAT_EXPECTED(DataLayout::parse("^"),
+ FailedWithMessage("unknown specifier '^'"));
+ EXPECT_THAT_EXPECTED(DataLayout::parse("m:v"),
+ FailedWithMessage("unknown mangling specifier"));
EXPECT_THAT_EXPECTED(
DataLayout::parse("n0"),
- FailedWithMessage("Zero width native integer type in datalayout string"));
- EXPECT_THAT_EXPECTED(
- DataLayout::parse("p16777216:64:64:64"),
- FailedWithMessage("Invalid address space, must be a 24-bit integer"));
+ FailedWithMessage("<size> must be a non-zero 24-bit integer"));
+ EXPECT_THAT_EXPECTED(DataLayout::parse("p16777216:64:64:64"),
+ FailedWithMessage("<n> must be a 24-bit integer"));
EXPECT_THAT_EXPECTED(
DataLayout::parse("a1:64"),
- FailedWithMessage("Sized aggregate specification in datalayout string"));
- EXPECT_THAT_EXPECTED(
- DataLayout::parse("a:"),
- FailedWithMessage("Trailing separator in datalayout string"));
+ FailedWithMessage("<size> is not applicable to aggregates"));
+ EXPECT_THAT_EXPECTED(DataLayout::parse("a:"),
+ FailedWithMessage("<abi> is required"));
EXPECT_THAT_EXPECTED(
DataLayout::parse("p:48:52"),
- FailedWithMessage("number of bits must be a byte width multiple"));
+ FailedWithMessage("<abi> must be a power of two times the byte width"));
EXPECT_THAT_EXPECTED(
DataLayout::parse("e-p"),
- FailedWithMessage(
- "Missing size specification for pointer in datalayout string"));
+ FailedWithMessage("malformed specification, must be of the form "
+ "\"p[n]:<size>:<abi>[:<pref>][:<idx>]\""));
EXPECT_THAT_EXPECTED(
DataLayout::parse("e-p:64"),
- FailedWithMessage(
- "Missing alignment specification for pointer in datalayout string"));
+ FailedWithMessage("malformed specification, must be of the form "
+ "\"p[n]:<size>:<abi>[:<pref>][:<idx>]\""));
EXPECT_THAT_EXPECTED(
DataLayout::parse("m"),
- FailedWithMessage("Expected mangling specifier in datalayout string"));
+ FailedWithMessage("malformed specification, must be of the form "
+ "\"m:<mangling>\""));
EXPECT_THAT_EXPECTED(
DataLayout::parse("m."),
- FailedWithMessage("Unexpected trailing characters after mangling "
- "specifier in datalayout string"));
+ FailedWithMessage("malformed specification, must be of the form "
+ "\"m:<mangling>\""));
EXPECT_THAT_EXPECTED(
DataLayout::parse("f"),
- FailedWithMessage(
- "Missing alignment specification in datalayout string"));
- EXPECT_THAT_EXPECTED(
- DataLayout::parse(":32"),
- FailedWithMessage(
- "Expected token before separator in datalayout string"));
- EXPECT_THAT_EXPECTED(
- DataLayout::parse("i64:64:16"),
- FailedWithMessage(
- "Preferred alignment cannot be less than the ABI alignment"));
- EXPECT_THAT_EXPECTED(
- DataLayout::parse("i64:16:16777216"),
- FailedWithMessage(
- "Invalid preferred alignment, must be a 16bit integer"));
- EXPECT_THAT_EXPECTED(
- DataLayout::parse("i64:16777216:16777216"),
- FailedWithMessage("Invalid ABI alignment, must be a 16bit integer"));
+ FailedWithMessage("malformed specification, must be of the form "
+ "\"f<size>:<abi>[:<pref>]\""));
+ EXPECT_THAT_EXPECTED(DataLayout::parse(":32"),
+ FailedWithMessage("unknown specifier ':'"));
+ EXPECT_THAT_EXPECTED(DataLayout::parse("i64:64:16"),
+ FailedWithMessage("<pref> cannot be less than <abi>"));
+ EXPECT_THAT_EXPECTED(DataLayout::parse("i64:16:16777216"),
+ FailedWithMessage("<pref> must be a 16-bit integer"));
+ EXPECT_THAT_EXPECTED(DataLayout::parse("i64:16777216:16777216"),
+ FailedWithMessage("<abi> must be a 16-bit integer"));
EXPECT_THAT_EXPECTED(
DataLayout::parse("i16777216:16:16"),
- FailedWithMessage("Invalid bit width, must be a 24-bit integer"));
+ FailedWithMessage("<size> must be a non-zero 24-bit integer"));
+ EXPECT_THAT_EXPECTED(DataLayout::parse("p:32:32:16"),
+ FailedWithMessage("<pref> cannot be less than <abi>"));
EXPECT_THAT_EXPECTED(
- DataLayout::parse("p:32:32:16"),
- FailedWithMessage(
- "Preferred alignment cannot be less than the ABI alignment"));
- EXPECT_THAT_EXPECTED(DataLayout::parse("p:0:32:32"),
- FailedWithMessage("Invalid pointer size of 0 bytes"));
+ DataLayout::parse("p:0:32:32"),
+ FailedWithMessage("<size> must be a non-zero 24-bit integer"));
EXPECT_THAT_EXPECTED(
DataLayout::parse("p:64:24:64"),
- FailedWithMessage("Pointer ABI alignment must be a power of 2"));
+ FailedWithMessage("<abi> must be a power of two times the byte width"));
EXPECT_THAT_EXPECTED(
DataLayout::parse("p:64:64:24"),
- FailedWithMessage("Pointer preferred alignment must be a power of 2"));
+ FailedWithMessage("<pref> must be a power of two times the byte width"));
EXPECT_THAT_EXPECTED(
DataLayout::parse("p:64:64:64:128"),
- FailedWithMessage("Index width cannot be larger than pointer width"));
- EXPECT_THAT_EXPECTED(
- DataLayout::parse("v128:0:128"),
- FailedWithMessage(
- "ABI alignment specification must be >0 for non-aggregate types"));
+ FailedWithMessage("index size cannot be larger than pointer size"));
+ EXPECT_THAT_EXPECTED(DataLayout::parse("v128:0:128"),
+ FailedWithMessage("<abi> must be non-zero"));
EXPECT_THAT_EXPECTED(
DataLayout::parse("i32:24:32"),
- FailedWithMessage("Invalid ABI alignment, must be a power of 2"));
+ FailedWithMessage("<abi> must be a power of two times the byte width"));
EXPECT_THAT_EXPECTED(
DataLayout::parse("i32:32:24"),
- FailedWithMessage("Invalid preferred alignment, must be a power of 2"));
+ FailedWithMessage("<pref> must be a power of two times the byte width"));
EXPECT_THAT_EXPECTED(
DataLayout::parse("A16777216"),
- FailedWithMessage("Invalid address space, must be a 24-bit integer"));
+ FailedWithMessage("<address space> must be a 24-bit integer"));
EXPECT_THAT_EXPECTED(
DataLayout::parse("G16777216"),
- FailedWithMessage("Invalid address space, must be a 24-bit integer"));
+ FailedWithMessage("<address space> must be a 24-bit integer"));
EXPECT_THAT_EXPECTED(
DataLayout::parse("P16777216"),
- FailedWithMessage("Invalid address space, must be a 24-bit integer"));
+ FailedWithMessage("<address space> must be a 24-bit integer"));
EXPECT_THAT_EXPECTED(
DataLayout::parse("Fi24"),
- FailedWithMessage("Alignment is neither 0 nor a power of 2"));
- EXPECT_THAT_EXPECTED(
- DataLayout::parse("i8:16"),
- FailedWithMessage("Invalid ABI alignment, i8 must be naturally aligned"));
+ FailedWithMessage("<abi> must be a power of two times the byte width"));
+ EXPECT_THAT_EXPECTED(DataLayout::parse("i8:16"),
+ FailedWithMessage("<abi> must be exactly 8"));
EXPECT_THAT_EXPECTED(
DataLayout::parse("S24"),
- FailedWithMessage("Alignment is neither 0 nor a power of 2"));
+ FailedWithMessage("<size> must be a power of two times the byte width"));
}
TEST(DataLayout, LayoutStringFormat) {
More information about the llvm-commits
mailing list