diff options
Diffstat (limited to 'lld/ELF/Arch/Hexagon.cpp')
| -rw-r--r-- | lld/ELF/Arch/Hexagon.cpp | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/lld/ELF/Arch/Hexagon.cpp b/lld/ELF/Arch/Hexagon.cpp index 726e425b36dc..479131a24dcf 100644 --- a/lld/ELF/Arch/Hexagon.cpp +++ b/lld/ELF/Arch/Hexagon.cpp @@ -7,11 +7,18 @@ //===----------------------------------------------------------------------===// #include "InputFiles.h" +#include "OutputSections.h" #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" +#include "lld/Common/ErrorHandler.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/BinaryFormat/ELF.h" +#include "llvm/Support/ELFAttributes.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/HexagonAttributeParser.h" +#include "llvm/Support/HexagonAttributes.h" +#include "llvm/Support/LEB128.h" using namespace llvm; using namespace llvm::object; @@ -415,4 +422,116 @@ int64_t Hexagon::getImplicitAddend(const uint8_t *buf, RelType type) const { } } +namespace { +class HexagonAttributesSection final : public SyntheticSection { +public: + HexagonAttributesSection(Ctx &ctx) + : SyntheticSection(ctx, ".hexagon.attributes", SHT_HEXAGON_ATTRIBUTES, 0, + 1) {} + + size_t getSize() const override { return size; } + void writeTo(uint8_t *buf) override; + + static constexpr StringRef vendor = "hexagon"; + DenseMap<unsigned, unsigned> intAttr; + size_t size = 0; +}; +} // namespace + +static HexagonAttributesSection * +mergeAttributesSection(Ctx &ctx, + const SmallVector<InputSectionBase *, 0> §ions) { + ctx.in.hexagonAttributes = std::make_unique<HexagonAttributesSection>(ctx); + auto &merged = + static_cast<HexagonAttributesSection &>(*ctx.in.hexagonAttributes); + + // Collect all tags values from attributes section. + const auto &attributesTags = HexagonAttrs::getHexagonAttributeTags(); + for (const InputSectionBase *sec : sections) { + HexagonAttributeParser parser; + if (Error e = parser.parse(sec->content(), llvm::endianness::little)) + Warn(ctx) << sec << ": " << std::move(e); + for (const auto &tag : attributesTags) { + switch (HexagonAttrs::AttrType(tag.attr)) { + case HexagonAttrs::ARCH: + case HexagonAttrs::HVXARCH: + if (auto i = parser.getAttributeValue(tag.attr)) { + auto r = merged.intAttr.try_emplace(tag.attr, *i); + if (!r.second) + if (r.first->second < *i) + r.first->second = *i; + } + continue; + + case HexagonAttrs::HVXIEEEFP: + case HexagonAttrs::HVXQFLOAT: + case HexagonAttrs::ZREG: + case HexagonAttrs::AUDIO: + case HexagonAttrs::CABAC: + if (auto i = parser.getAttributeValue(tag.attr)) { + auto r = merged.intAttr.try_emplace(tag.attr, *i); + if (!r.second && r.first->second != *i) { + r.first->second |= *i; + } + } + continue; + } + } + } + + // The total size of headers: format-version [ <section-length> "vendor-name" + // [ <file-tag> <size>. + size_t size = 5 + merged.vendor.size() + 1 + 5; + for (auto &attr : merged.intAttr) + if (attr.second != 0) + size += getULEB128Size(attr.first) + getULEB128Size(attr.second); + merged.size = size; + return &merged; +} + +void HexagonAttributesSection::writeTo(uint8_t *buf) { + const size_t size = getSize(); + uint8_t *const end = buf + size; + *buf = ELFAttrs::Format_Version; + write32(ctx, buf + 1, size - 1); + buf += 5; + + memcpy(buf, vendor.data(), vendor.size()); + buf += vendor.size() + 1; + + *buf = ELFAttrs::File; + write32(ctx, buf + 1, end - buf); + buf += 5; + + for (auto &attr : intAttr) { + if (attr.second == 0) + continue; + buf += encodeULEB128(attr.first, buf); + buf += encodeULEB128(attr.second, buf); + } +} + +void elf::mergeHexagonAttributesSections(Ctx &ctx) { + // Find the first input SHT_HEXAGON_ATTRIBUTES; return if not found. + size_t place = + llvm::find_if(ctx.inputSections, + [](auto *s) { return s->type == SHT_HEXAGON_ATTRIBUTES; }) - + ctx.inputSections.begin(); + if (place == ctx.inputSections.size()) + return; + + // Extract all SHT_HEXAGON_ATTRIBUTES sections into `sections`. + SmallVector<InputSectionBase *, 0> sections; + llvm::erase_if(ctx.inputSections, [&](InputSectionBase *s) { + if (s->type != SHT_HEXAGON_ATTRIBUTES) + return false; + sections.push_back(s); + return true; + }); + + // Add the merged section. + ctx.inputSections.insert(ctx.inputSections.begin() + place, + mergeAttributesSection(ctx, sections)); +} + void elf::setHexagonTargetInfo(Ctx &ctx) { ctx.target.reset(new Hexagon(ctx)); } |
