Skip to content

Commit

Permalink
[ARM] Rewrite ARMAttributeParser
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
MaskRay committed Mar 5, 2020
1 parent f23df1b commit 791efb1
Show file tree
Hide file tree
Showing 11 changed files with 520 additions and 687 deletions.
9 changes: 7 additions & 2 deletions lld/ELF/InputFiles.cpp
Expand Up @@ -840,8 +840,13 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &sec) {
break;
ARMAttributeParser attributes;
ArrayRef<uint8_t> contents = check(this->getObj().getSectionContents(&sec));
attributes.parse(contents, config->ekind == ELF32LEKind ? support::little
: support::big);
if (Error e = attributes.parse(contents, config->ekind == ELF32LEKind
? support::little
: support::big)) {
auto *isec = make<InputSection>(*this, sec, name);
warn(toString(isec) + ": " + llvm::toString(std::move(e)));
break;
}
updateSupportedARMFeatures(attributes);
updateARMVFPArgs(attributes, this);

Expand Down
4 changes: 2 additions & 2 deletions lld/test/ELF/arm-tag-vfp-args-illegal.s
@@ -1,8 +1,8 @@
// REQUIRES:arm
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
// RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s
// RUN: ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s

// CHECK: arm-tag-vfp-args-illegal.s.tmp.o: unknown Tag_ABI_VFP_args value: 5
// CHECK: {{.*}}.o:(.ARM.attributes): unknown ABI_VFP_args value: 5
.arch armv7-a
.eabi_attribute 20, 1
.eabi_attribute 21, 1
Expand Down
6 changes: 3 additions & 3 deletions lld/test/ELF/invalid/bad-arm-attributes.s
@@ -1,8 +1,8 @@
# REQUIRES: arm
# RUN: llvm-mc -filetype=obj -triple=arm-unknown-linux %s -o %t
# RUN: ld.lld %t -o /dev/null 2>&1 | FileCheck %s
# RUN: llvm-mc -filetype=obj -triple=arm-unknown-linux %s -o %t.o
# RUN: ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s

# CHECK: invalid subsection length 0 at offset 1
# CHECK: {{.*}}.o:(.ARM.attributes): unrecognized format-version: 0x0

.section .ARM.attributes,"a",%0x70000003
.quad 0
8 changes: 0 additions & 8 deletions lld/test/ELF/invalid/bad-arm-attributes2.s

This file was deleted.

3 changes: 2 additions & 1 deletion llvm/include/llvm/Object/ELFObjectFile.h
Expand Up @@ -380,7 +380,8 @@ template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
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;
}
}
Expand Down
171 changes: 65 additions & 106 deletions llvm/include/llvm/Support/ARMAttributeParser.h
Expand Up @@ -11,128 +11,87 @@

#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>

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[];

uint64_t ParseInteger(const uint8_t *Data, uint32_t &Offset);
StringRef ParseString(const uint8_t *Data, uint32_t &Offset);

void IntegerAttribute(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);
void StringAttribute(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
uint32_t &Offset);

void PrintAttribute(unsigned Tag, unsigned Value, StringRef ValueDesc);

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) {}
static const DisplayHandler displayRoutines[];

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);

Error stringAttribute(ARMBuildAttrs::AttrType tag);

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);

ARMAttributeParser() : SW(nullptr) { }
public:
ARMAttributeParser(ScopedPrinter *sw) : sw(sw) {}
ARMAttributeParser() : sw(nullptr) {}
~ARMAttributeParser() { static_cast<void>(!cursor.takeError()); }

void parse(ArrayRef<uint8_t> Section, support::endianness E);
Error parse(ArrayRef<uint8_t> section, support::endianness endian);

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;
}
};

Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/Support/DataExtractor.h
Expand Up @@ -197,6 +197,8 @@ class DataExtractor {
/// 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.
///
Expand Down
9 changes: 7 additions & 2 deletions llvm/lib/Object/ELFObjectFile.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit 791efb1

Please sign in to comment.