1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

[ARM] Rewrite ARMAttributeParser

* Delete boilerplate
* Change functions to return `Error`
* Test parsing errors
* Update callers of ARMAttributeParser::parse() to check the `Error` return value.

Since this patch touches nearly everything in the file, I apply
http://llvm.org/docs/Proposals/VariableNames.html and change variable
names to lower case.

Reviewed By: compnerd

Differential Revision: https://reviews.llvm.org/D75015
This commit is contained in:
Fangrui Song 2020-02-21 11:32:33 -08:00
parent bcae288a5c
commit 02300509f3
7 changed files with 503 additions and 667 deletions

View File

@ -380,7 +380,8 @@ protected:
if (Contents[0] != ARMBuildAttrs::Format_Version || Contents.size() == 1)
return Error::success();
Attributes.parse(Contents, ELFT::TargetEndianness);
if (Error E = Attributes.parse(Contents, ELFT::TargetEndianness))
return E;
break;
}
}

View File

@ -11,7 +11,10 @@
#include "ARMBuildAttributes.h"
#include "ScopedPrinter.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <map>
@ -19,120 +22,76 @@ namespace llvm {
class StringRef;
class ARMAttributeParser {
ScopedPrinter *SW;
ScopedPrinter *sw;
std::map<unsigned, unsigned> Attributes;
std::map<unsigned, unsigned> attributes;
DataExtractor de{ArrayRef<uint8_t>{}, true, 0};
DataExtractor::Cursor cursor{0};
struct DisplayHandler {
ARMBuildAttrs::AttrType Attribute;
void (ARMAttributeParser::*Routine)(ARMBuildAttrs::AttrType,
const uint8_t *, uint32_t &);
ARMBuildAttrs::AttrType attribute;
Error (ARMAttributeParser::*routine)(ARMBuildAttrs::AttrType);
};
static const DisplayHandler DisplayRoutines[];
static const DisplayHandler displayRoutines[];
uint64_t ParseInteger(const uint8_t *Data, uint32_t &Offset);
StringRef ParseString(const uint8_t *Data, uint32_t &Offset);
Error parseAttributeList(uint32_t length);
void parseIndexList(SmallVectorImpl<uint8_t> &indexList);
Error parseSubsection(uint32_t length);
Error parseStringAttribute(const char *name, ARMBuildAttrs::AttrType tag,
const ArrayRef<const char *> array);
void printAttribute(unsigned tag, unsigned value, StringRef valueDesc);
void IntegerAttribute(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void StringAttribute(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
Error stringAttribute(ARMBuildAttrs::AttrType tag);
void PrintAttribute(unsigned Tag, unsigned Value, StringRef ValueDesc);
Error CPU_arch(ARMBuildAttrs::AttrType tag);
Error CPU_arch_profile(ARMBuildAttrs::AttrType tag);
Error ARM_ISA_use(ARMBuildAttrs::AttrType tag);
Error THUMB_ISA_use(ARMBuildAttrs::AttrType tag);
Error FP_arch(ARMBuildAttrs::AttrType tag);
Error WMMX_arch(ARMBuildAttrs::AttrType tag);
Error Advanced_SIMD_arch(ARMBuildAttrs::AttrType tag);
Error MVE_arch(ARMBuildAttrs::AttrType tag);
Error PCS_config(ARMBuildAttrs::AttrType tag);
Error ABI_PCS_R9_use(ARMBuildAttrs::AttrType tag);
Error ABI_PCS_RW_data(ARMBuildAttrs::AttrType tag);
Error ABI_PCS_RO_data(ARMBuildAttrs::AttrType tag);
Error ABI_PCS_GOT_use(ARMBuildAttrs::AttrType tag);
Error ABI_PCS_wchar_t(ARMBuildAttrs::AttrType tag);
Error ABI_FP_rounding(ARMBuildAttrs::AttrType tag);
Error ABI_FP_denormal(ARMBuildAttrs::AttrType tag);
Error ABI_FP_exceptions(ARMBuildAttrs::AttrType tag);
Error ABI_FP_user_exceptions(ARMBuildAttrs::AttrType tag);
Error ABI_FP_number_model(ARMBuildAttrs::AttrType tag);
Error ABI_align_needed(ARMBuildAttrs::AttrType tag);
Error ABI_align_preserved(ARMBuildAttrs::AttrType tag);
Error ABI_enum_size(ARMBuildAttrs::AttrType tag);
Error ABI_HardFP_use(ARMBuildAttrs::AttrType tag);
Error ABI_VFP_args(ARMBuildAttrs::AttrType tag);
Error ABI_WMMX_args(ARMBuildAttrs::AttrType tag);
Error ABI_optimization_goals(ARMBuildAttrs::AttrType tag);
Error ABI_FP_optimization_goals(ARMBuildAttrs::AttrType tag);
Error compatibility(ARMBuildAttrs::AttrType tag);
Error CPU_unaligned_access(ARMBuildAttrs::AttrType tag);
Error FP_HP_extension(ARMBuildAttrs::AttrType tag);
Error ABI_FP_16bit_format(ARMBuildAttrs::AttrType tag);
Error MPextension_use(ARMBuildAttrs::AttrType tag);
Error DIV_use(ARMBuildAttrs::AttrType tag);
Error DSP_extension(ARMBuildAttrs::AttrType tag);
Error T2EE_use(ARMBuildAttrs::AttrType tag);
Error Virtualization_use(ARMBuildAttrs::AttrType tag);
Error nodefaults(ARMBuildAttrs::AttrType tag);
void CPU_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void CPU_arch_profile(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void ARM_ISA_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void THUMB_ISA_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void FP_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void WMMX_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void Advanced_SIMD_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void MVE_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void PCS_config(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void ABI_PCS_R9_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void ABI_PCS_RW_data(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void ABI_PCS_RO_data(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void ABI_PCS_GOT_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void ABI_PCS_wchar_t(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void ABI_FP_rounding(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void ABI_FP_denormal(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void ABI_FP_exceptions(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void ABI_FP_user_exceptions(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void ABI_FP_number_model(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void ABI_align_needed(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void ABI_align_preserved(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void ABI_enum_size(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void ABI_HardFP_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void ABI_VFP_args(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void ABI_WMMX_args(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void ABI_optimization_goals(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void ABI_FP_optimization_goals(ARMBuildAttrs::AttrType Tag,
const uint8_t *Data, uint32_t &Offset);
void compatibility(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void CPU_unaligned_access(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void FP_HP_extension(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void ABI_FP_16bit_format(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void MPextension_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void DIV_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void DSP_extension(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void T2EE_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void Virtualization_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void nodefaults(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void ParseAttributeList(const uint8_t *Data, uint32_t &Offset,
uint32_t Length);
void ParseIndexList(const uint8_t *Data, uint32_t &Offset,
SmallVectorImpl<uint8_t> &IndexList);
void ParseSubsection(const uint8_t *Data, uint32_t Length);
public:
ARMAttributeParser(ScopedPrinter *SW) : SW(SW) {}
ARMAttributeParser(ScopedPrinter *sw) : sw(sw) {}
ARMAttributeParser() : sw(nullptr) {}
~ARMAttributeParser() { static_cast<void>(!cursor.takeError()); }
ARMAttributeParser() : SW(nullptr) { }
Error parse(ArrayRef<uint8_t> section, support::endianness endian);
void parse(ArrayRef<uint8_t> Section, support::endianness E);
bool hasAttribute(unsigned tag) const { return attributes.count(tag); }
bool hasAttribute(unsigned Tag) const {
return Attributes.count(Tag);
}
unsigned getAttributeValue(unsigned Tag) const {
return Attributes.find(Tag)->second;
unsigned getAttributeValue(unsigned tag) const {
return attributes.find(tag)->second;
}
};

View File

@ -197,6 +197,8 @@ public:
/// is out of bounds, a default-initialized StringRef will be returned.
StringRef getBytes(uint64_t *OffsetPtr, uint64_t Length) const;
StringRef getCStrRef(Cursor &C) const { return getCStrRef(&C.Offset); }
/// Extract an unsigned integer of size \a byte_size from \a
/// *offset_ptr.
///

View File

@ -157,8 +157,10 @@ SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const {
SubtargetFeatures ELFObjectFileBase::getARMFeatures() const {
SubtargetFeatures Features;
ARMAttributeParser Attributes;
if (Error E = getBuildAttributes(Attributes))
if (Error E = getBuildAttributes(Attributes)) {
consumeError(std::move(E));
return SubtargetFeatures();
}
// both ARMv7-M and R have to support thumb hardware div
bool isV7 = false;
@ -305,8 +307,11 @@ void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const {
return;
ARMAttributeParser Attributes;
if (Error E = getBuildAttributes(Attributes))
if (Error E = getBuildAttributes(Attributes)) {
// TODO Propagate Error.
consumeError(std::move(E));
return;
}
std::string Triple;
// Default to ARM, but use the triple if it's been set.

File diff suppressed because it is too large Load Diff

View File

@ -2690,7 +2690,9 @@ template <> void ELFDumper<ELF32LE>::printAttributes() {
if (Contents.size() == 1)
continue;
ARMAttributeParser(&W).parse(Contents, support::little);
// TODO: Print error and delete the redundant FormatVersion check above.
if (Error E = ARMAttributeParser(&W).parse(Contents, support::little))
consumeError(std::move(E));
}
}

View File

@ -34,16 +34,55 @@ bool testBuildAttr(unsigned Tag, unsigned Value,
reinterpret_cast<const uint8_t*>(OS.str().c_str()), OS.str().size());
ARMAttributeParser Parser;
Parser.parse(Bytes, support::little);
cantFail(Parser.parse(Bytes, support::little));
return (Parser.hasAttribute(ExpectedTag) &&
Parser.getAttributeValue(ExpectedTag) == ExpectedValue);
}
void testParseError(ArrayRef<uint8_t> bytes, const char *msg) {
ARMAttributeParser parser;
Error e = parser.parse(bytes, support::little);
EXPECT_STREQ(toString(std::move(e)).c_str(), msg);
}
bool testTagString(unsigned Tag, const char *name) {
return ARMBuildAttrs::AttrTypeAsString(Tag).str() == name;
}
TEST(ARMAttributeParser, UnrecognizedFormatVersion) {
static const uint8_t bytes[] = {1};
testParseError(bytes, "unrecognized format-version: 0x1");
}
TEST(ARMAttributeParser, InvalidSubsectionLength) {
static const uint8_t bytes[] = {'A', 3, 0, 0, 0};
testParseError(bytes, "invalid subsection length 3 at offset 0x1");
}
TEST(ARMAttributeParser, UnrecognizedVendorName) {
static const uint8_t bytes[] = {'A', 7, 0, 0, 0, 'x', 'y', 0};
testParseError(bytes, "unrecognized vendor-name: xy");
}
TEST(ARMAttributeParser, InvalidAttributeSize) {
static const uint8_t bytes[] = {'A', 15, 0, 0, 0, 'a', 'e', 'a',
'b', 'i', 0, 4, 4, 0, 0, 0};
testParseError(bytes, "invalid attribute size 4 at offset 0xb");
}
TEST(ARMAttributeParser, UnrecognizedTag) {
static const uint8_t bytes[] = {'A', 15, 0, 0, 0, 'a', 'e', 'a',
'b', 'i', 0, 4, 5, 0, 0, 0};
testParseError(bytes, "unrecognized tag 0x4 at offset 0xb");
}
TEST(ARMAttributeParser, UnknownCPU_arch) {
static const uint8_t bytes[] = {'A', 15, 0, 0, 0, 'a', 'e', 'a', 'b',
'i', 0, 1, 7, 0, 0, 0, 6, 22};
testParseError(bytes, "unknown CPU_arch value: 22");
}
TEST(CPUArchBuildAttr, testBuildAttr) {
EXPECT_TRUE(testTagString(6, "Tag_CPU_arch"));