From 8c55c01d2a68cac0fa31bcc5150f715a94a6b549 Mon Sep 17 00:00:00 2001 From: Shankar Easwaran Date: Fri, 22 Feb 2013 18:01:08 +0000 Subject: [PATCH] sort quickdata for the hexagon target llvm-svn: 175904 --- lld/lib/ReaderWriter/ELF/Chunk.h | 4 +- lld/lib/ReaderWriter/ELF/DefaultLayout.h | 5 ++ lld/lib/ReaderWriter/ELF/HeaderChunks.h | 24 ++++--- .../ELF/Hexagon/HexagonSectionChunks.h | 76 +++++++++++++++++++++ .../ELF/Hexagon/HexagonTargetHandler.h | 61 ++++++++++++++++- lld/lib/ReaderWriter/ELF/SectionChunks.h | 13 ++-- lld/lib/ReaderWriter/ELF/SegmentChunks.h | 5 +- lld/lib/ReaderWriter/ELF/Writer.cpp | 9 ++- .../elf/Inputs/quickdata-sort-test.o.elf-hexagon | Bin 0 -> 1385 bytes lld/test/elf/hexagon-quickdata-sort.test | 12 ++++ 10 files changed, 185 insertions(+), 24 deletions(-) create mode 100644 lld/lib/ReaderWriter/ELF/Hexagon/HexagonSectionChunks.h create mode 100644 lld/test/elf/Inputs/quickdata-sort-test.o.elf-hexagon create mode 100644 lld/test/elf/hexagon-quickdata-sort.test diff --git a/lld/lib/ReaderWriter/ELF/Chunk.h b/lld/lib/ReaderWriter/ELF/Chunk.h index 732403b..92c3a11 100644 --- a/lld/lib/ReaderWriter/ELF/Chunk.h +++ b/lld/lib/ReaderWriter/ELF/Chunk.h @@ -69,9 +69,11 @@ public: uint64_t virtualAddr() const { return _start; } // Does the chunk occupy memory during execution ? uint64_t memSize() const { return _msize; } - void setMemSize(uint64_t msize) { _msize = msize; } + void setMemSize(uint64_t msize) { _msize = msize; } // Writer the chunk virtual void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer) = 0; + // Finalize the chunk before assigning offsets/virtual addresses + virtual void doPreFlight() = 0; // Finalize the chunk before writing virtual void finalize() = 0; diff --git a/lld/lib/ReaderWriter/ELF/DefaultLayout.h b/lld/lib/ReaderWriter/ELF/DefaultLayout.h index d2bdca5..a3dad87 100644 --- a/lld/lib/ReaderWriter/ELF/DefaultLayout.h +++ b/lld/lib/ReaderWriter/ELF/DefaultLayout.h @@ -208,6 +208,11 @@ public: si->finalize(); } + inline void doPreFlight() { + for (auto &si : _sections) + si->doPreFlight(); + } + inline bool findAtomAddrByName(StringRef name, uint64_t &addr) { for (auto sec : _sections) if (auto section = dyn_cast >(sec)) diff --git a/lld/lib/ReaderWriter/ELF/HeaderChunks.h b/lld/lib/ReaderWriter/ELF/HeaderChunks.h index 84bcde9..6282ee9 100644 --- a/lld/lib/ReaderWriter/ELF/HeaderChunks.h +++ b/lld/lib/ReaderWriter/ELF/HeaderChunks.h @@ -52,7 +52,9 @@ public: void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer); - void finalize() { } + virtual void doPreFlight() {} + + void finalize() {} private: Elf_Ehdr _eh; @@ -145,11 +147,11 @@ public: return _ph.end(); } - void finalize() { } + virtual void doPreFlight() {} - int64_t entsize() { - return sizeof(Elf_Phdr); - } + void finalize() {} + + int64_t entsize() { return sizeof(Elf_Phdr); } int64_t numHeaders() { return _ph.size(); @@ -249,12 +251,12 @@ public: } void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer); - - void finalize() { } - - inline uint16_t fileSize() { - return sizeof(Elf_Shdr) * _sectionInfo.size(); - } + + virtual void doPreFlight() {} + + void finalize() {} + + inline uint16_t fileSize() { return sizeof(Elf_Shdr) * _sectionInfo.size(); } inline int64_t entsize() { return sizeof(Elf_Shdr); diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonSectionChunks.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonSectionChunks.h new file mode 100644 index 0000000..ec81e31 --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonSectionChunks.h @@ -0,0 +1,76 @@ +//===- lib/ReaderWriter/ELF/Hexagon/HexagonSectionChunks.h-----------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "HexagonTargetHandler.h" + +namespace lld { +namespace elf { +typedef llvm::object::ELFType HexagonELFType; +template class HexagonTargetLayout; +class HexagonTargetInfo; + +/// \brief Handle Hexagon SData section +template +class SDataSection : public AtomSection { +public: + SDataSection(const HexagonTargetInfo &hti) + : AtomSection( + hti, ".sdata", DefinedAtom::typeDataFast, 0, + HexagonTargetLayout::ORDER_SDATA) { + this->_type = SHT_PROGBITS; + this->_flags = SHF_ALLOC | SHF_WRITE; + } + + /// \brief Finalize the section contents before writing + virtual void doPreFlight(); + + /// \brief Does this section have an output segment. + virtual bool hasOutputSegment() { return true; } + + const AtomLayout &appendAtom(const Atom *atom) { + const DefinedAtom *definedAtom = cast(atom); + DefinedAtom::Alignment atomAlign = definedAtom->alignment(); + uint64_t align2 = 1u << atomAlign.powerOf2; + this->_atoms.push_back(new (this->_alloc) AtomLayout(atom, 0, 0)); + // Set the section alignment to the largest alignment + // std::max doesnot support uint64_t + if (this->_align2 < align2) + this->_align2 = align2; + return *(this->_atoms.back()); + } + +}; // SDataSection + +template +void SDataSection::doPreFlight() { + // sort the atoms on the alignments they have been set + std::stable_sort(this->_atoms.begin(), this->_atoms.end(), + [](const AtomLayout * A, const AtomLayout * B) { + const DefinedAtom *definedAtomA = cast(A->_atom); + const DefinedAtom *definedAtomB = cast(B->_atom); + int64_t align2A = 1 << definedAtomA->alignment().powerOf2; + int64_t align2B = 1 << definedAtomB->alignment().powerOf2; + return align2A < align2B; + }); + + // Set the fileOffset, and the appropriate size of the section + for (auto &ai : this->_atoms) { + const DefinedAtom *definedAtom = cast(ai->_atom); + DefinedAtom::Alignment atomAlign = definedAtom->alignment(); + uint64_t fOffset = this->alignOffset(this->fileSize(), atomAlign); + uint64_t mOffset = this->alignOffset(this->memSize(), atomAlign); + ai->_fileOffset = fOffset; + this->_fsize = fOffset + definedAtom->size(); + this->_msize = mOffset + definedAtom->size(); + } +} // finalize + +} // elf +} // lld + diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h index 41a620f..b1169cd 100644 --- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h @@ -13,6 +13,7 @@ #include "DefaultTargetHandler.h" #include "ExecutableAtoms.h" #include "HexagonRelocationHandler.h" +#include "HexagonSectionChunks.h" #include "TargetLayout.h" namespace lld { @@ -75,6 +76,64 @@ public: } }; +/// \brief TargetLayout for Hexagon +template +class HexagonTargetLayout LLVM_FINAL : public TargetLayout { + +public: + enum HexagonSectionOrder { + ORDER_SDATA = 205 + }; + + HexagonTargetLayout(const HexagonTargetInfo &hti) + : TargetLayout(hti), _sdataSection(nullptr) { + _sdataSection = new (_alloc) SDataSection(hti); + } + + /// \brief Return the section order for a input section + virtual Layout::SectionOrder getSectionOrder( + StringRef name, int32_t contentType, int32_t contentPermissions) { + if (contentType == DefinedAtom::typeDataFast) + return ORDER_SDATA; + + return DefaultLayout::getSectionOrder(name, contentType, + contentPermissions); + } + + /// \brief This maps the input sections to the output section names + virtual StringRef getSectionName(StringRef name, const int32_t contentType, + const int32_t contentPermissions) { + if (contentType == DefinedAtom::typeDataFast) + return ".sdata"; + return DefaultLayout::getSectionName(name, contentType, + contentPermissions); + } + + /// \brief Gets or creates a section. + virtual AtomSection * + createSection(StringRef name, int32_t contentType, + DefinedAtom::ContentPermissions contentPermissions, + Layout::SectionOrder sectionOrder) { + if (contentType == DefinedAtom::typeDataFast) + return _sdataSection; + return DefaultLayout::createSection( + name, contentType, contentPermissions, sectionOrder); + } + + /// \brief get the segment type for the section thats defined by the target + virtual Layout::SegmentType + getSegmentType(Section *section) const { + if (section->order() == ORDER_SDATA) + return PT_LOAD; + + return DefaultLayout::getSegmentType(section); + } + +private: + llvm::BumpPtrAllocator _alloc; + SDataSection *_sdataSection; +}; + /// \brief TargetHandler for Hexagon class HexagonTargetHandler LLVM_FINAL : public DefaultTargetHandler { @@ -95,7 +154,7 @@ public: private: HexagonTargetRelocationHandler _relocationHandler; - TargetLayout _targetLayout; + HexagonTargetLayout _targetLayout; HexagonTargetAtomHandler _targetAtomHandler; }; } // end namespace elf diff --git a/lld/lib/ReaderWriter/ELF/SectionChunks.h b/lld/lib/ReaderWriter/ELF/SectionChunks.h index 118de40..8b4c87b 100644 --- a/lld/lib/ReaderWriter/ELF/SectionChunks.h +++ b/lld/lib/ReaderWriter/ELF/SectionChunks.h @@ -39,13 +39,12 @@ public: /// \param type the ELF SHT_* type of the section. Section(const ELFTargetInfo &ti, StringRef name, typename Chunk::Kind k = Chunk::K_ELFSection) - : Chunk(name, k, ti), - _flags(0), - _entSize(0), - _type(0), - _link(0), - _info(0), - _segmentType(SHT_NULL) {} + : Chunk(name, k, ti), _flags(0), _entSize(0), _type(0), _link(0), + _info(0), _segmentType(SHT_NULL) {} + + /// \brief Modify the section contents before assigning virtual addresses + // or assigning file offsets + virtual void doPreFlight() {} /// \brief Finalize the section contents before writing virtual void finalize() {} diff --git a/lld/lib/ReaderWriter/ELF/SegmentChunks.h b/lld/lib/ReaderWriter/ELF/SegmentChunks.h index 9be989a..fb772dd 100644 --- a/lld/lib/ReaderWriter/ELF/SegmentChunks.h +++ b/lld/lib/ReaderWriter/ELF/SegmentChunks.h @@ -159,8 +159,11 @@ public: _sections.insert(_sections.begin(), c); } + // Finalize the segment before assigning File Offsets / Virtual addresses + inline void doPreFlight() {} + // Finalize the segment, before we want to write to the output file - inline void finalize() { } + inline void finalize() {} // For LLVM RTTI static inline bool classof(const Chunk *c) { diff --git a/lld/lib/ReaderWriter/ELF/Writer.cpp b/lld/lib/ReaderWriter/ELF/Writer.cpp index 0cd0e55..4272eb8 100644 --- a/lld/lib/ReaderWriter/ELF/Writer.cpp +++ b/lld/lib/ReaderWriter/ELF/Writer.cpp @@ -231,11 +231,14 @@ void ExecutableWriter::finalizeDefaultAtomValues() { (*endAtomIter)->_virtualAddr = (*phe)->p_vaddr + (*phe)->p_memsz; } -template -error_code -ExecutableWriter::writeFile(const File &file, StringRef path) { +template +error_code ExecutableWriter::writeFile(const File &file, StringRef path) { buildChunks(file); + // Call the preFlight callbacks to modify the sections and the atoms + // contained in them, in anyway the targets may want + _layout->doPreFlight(); + // Create the default sections like the symbol table, string table, and the // section string table createDefaultSections(); diff --git a/lld/test/elf/Inputs/quickdata-sort-test.o.elf-hexagon b/lld/test/elf/Inputs/quickdata-sort-test.o.elf-hexagon new file mode 100644 index 0000000000000000000000000000000000000000..03d0287071295a7c6b6661fcf8004e0472cb8b42 GIT binary patch literal 1385 zcmah|O;6iE5FN9DmNY<(!~vm7=F~)@7N$mms0Tv&5u{uqP8^dEsTB%{#F3gq)t>rG z`eXWcdh4xyZ+9nlt*9Akcix+QGoBsWU*C1#2SFfef&7r1iTuWa!Ah;5F1xa0Q6OtJ zUa<_@hjzOe)vq6Bli_GGk9xDKcGUfpjiS@|_*I&mHlj36<71I{Iv;2K0em)b{-dI7 z^f{CGwx9JS9!#f@I6QR(dz>Ihf8u@W{h1eA0kf>a0!l1^X8153kM1*VdbK}*g!9<& zQa6V@Pw#)|b(|Hgtkapk#Mx7E&I6321FxH^G#`5+4t27y;G<72Dp4*?TI?YgOaWZu02tw_^zaT1Fk($r6^S7Pog%BPd!hW4p@(=ATZPU+jon{|=X9