aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/IR/DataLayout.cpp
diff options
context:
space:
mode:
authorSergei Barannikov <barannikov88@gmail.com>2024-08-20 11:25:49 +0300
committerGitHub <noreply@github.com>2024-08-20 11:25:49 +0300
commitc91cc459d396dd4625d3dbf9a2af6fac8151eb4b (patch)
treee61da7b5804f790102f79e5c54e0f5bf6cb14cab /llvm/lib/IR/DataLayout.cpp
parent513e0af0a940f3a823f8f0e83189cb33cb81496f (diff)
downloadllvm-c91cc459d396dd4625d3dbf9a2af6fac8151eb4b.zip
llvm-c91cc459d396dd4625d3dbf9a2af6fac8151eb4b.tar.gz
llvm-c91cc459d396dd4625d3dbf9a2af6fac8151eb4b.tar.bz2
[DataLayout] Refactor the rest of `parseSpecification` (#104545)
The aim is to improve test coverage of data layout string parsing. Pull Request: https://github.com/llvm/llvm-project/pull/104545
Diffstat (limited to 'llvm/lib/IR/DataLayout.cpp')
-rw-r--r--llvm/lib/IR/DataLayout.cpp140
1 files changed, 43 insertions, 97 deletions
diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp
index 5efdaac..d295d1f 100644
--- a/llvm/lib/IR/DataLayout.cpp
+++ b/llvm/lib/IR/DataLayout.cpp
@@ -268,10 +268,6 @@ Expected<DataLayout> DataLayout::parse(StringRef LayoutString) {
return Layout;
}
-static Error reportError(const Twine &Message) {
- return createStringError(inconvertibleErrorCode(), Message);
-}
-
static Error createSpecFormatError(Twine Format) {
return createStringError("malformed specification, must be of the form \"" +
Format + "\"");
@@ -336,46 +332,6 @@ static Error parseAlignment(StringRef Str, Align &Alignment, StringRef Name,
return Error::success();
}
-/// 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");
- 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");
- 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;
- return Error::success();
-}
-
-static Error getAddrSpace(StringRef R, unsigned &AddrSpace) {
- if (Error Err = getInt(R, AddrSpace))
- return Err;
- if (!isUInt<24>(AddrSpace))
- return reportError("Invalid address space, must be a 24-bit integer");
- return Error::success();
-}
-
Error DataLayout::parsePrimitiveSpec(StringRef Spec) {
// [ifv]<size>:<abi>[:<pref>]
SmallVector<StringRef, 3> Components;
@@ -536,55 +492,45 @@ Error DataLayout::parseSpecification(StringRef Spec) {
if (Specifier == 'p')
return parsePointerSpec(Spec);
- // Split at ':'.
- std::pair<StringRef, StringRef> Split;
- if (Error Err = ::split(Spec, ':', Split))
- return Err;
-
- // Aliases used below.
- StringRef &Tok = Split.first; // Current token.
- StringRef &Rest = Split.second; // The rest of the string.
-
- char SpecifierChar = Tok.front();
- Tok = Tok.substr(1);
-
- switch (SpecifierChar) {
+ StringRef Rest = Spec.drop_front();
+ switch (Specifier) {
case 's':
// Deprecated, but ignoring here to preserve loading older textual llvm
// ASM file
break;
- case 'E':
- BigEndian = true;
- break;
case 'e':
- BigEndian = false;
+ case 'E':
+ if (!Rest.empty())
+ return createStringError(
+ "malformed specification, must be just 'e' or 'E'");
+ BigEndian = Specifier == 'E';
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))
return Err;
+ LegalIntWidths.push_back(BitWidth);
}
break;
case 'S': { // Stack natural alignment.
- uint64_t Alignment;
- if (Error Err = getIntInBytes(Tok, Alignment))
+ // S<size>
+ if (Rest.empty())
+ return createSpecFormatError("S<size>");
+ Align Alignment;
+ if (Error Err = parseAlignment(Rest, Alignment, "stack natural"))
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>
+ if (Rest.empty())
+ return createSpecFormatError("F<type><abi>");
+ char Type = Rest.front();
+ Rest = Rest.drop_front();
+ switch (Type) {
case 'i':
TheFunctionPtrAlignType = FunctionPtrAlignType::Independent;
break;
@@ -592,44 +538,44 @@ 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"))
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))
+ if (Rest.empty())
+ return createSpecFormatError("P<address space>");
+ if (Error Err = parseAddrSpace(Rest, ProgramAddrSpace))
return Err;
break;
}
case 'A': { // Default stack/alloca address space.
- if (Error Err = getAddrSpace(Tok, AllocaAddrSpace))
+ if (Rest.empty())
+ return createSpecFormatError("A<address space>");
+ if (Error Err = parseAddrSpace(Rest, AllocaAddrSpace))
return Err;
break;
}
case 'G': { // Default address space for global variables.
- if (Error Err = getAddrSpace(Tok, DefaultGlobalsAddrSpace))
+ if (Rest.empty())
+ return createSpecFormatError("G<address space>");
+ if (Error Err = parseAddrSpace(Rest, DefaultGlobalsAddrSpace))
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");
+ 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 mode");
switch (Rest[0]) {
default:
- return reportError("Unknown mangling in datalayout string");
+ return createStringError("unknown mangling mode");
case 'e':
ManglingMode = MM_ELF;
break;
@@ -654,7 +600,7 @@ Error DataLayout::parseSpecification(StringRef Spec) {
}
break;
default:
- return reportError("Unknown specifier in datalayout string");
+ return createStringError("unknown specifier '" + Twine(Specifier) + "'");
}
return Error::success();