diff options
author | Sergei Barannikov <barannikov88@gmail.com> | 2024-08-20 11:25:49 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-20 11:25:49 +0300 |
commit | c91cc459d396dd4625d3dbf9a2af6fac8151eb4b (patch) | |
tree | e61da7b5804f790102f79e5c54e0f5bf6cb14cab /llvm/lib/IR/DataLayout.cpp | |
parent | 513e0af0a940f3a823f8f0e83189cb33cb81496f (diff) | |
download | llvm-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.cpp | 140 |
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(); |