//===- BranchIsland.h -----------------------------------------------------===// // // The MCLinker Project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef MCLD_LD_BRANCH_ISLAND_H #define MCLD_LD_BRANCH_ISLAND_H #ifdef ENABLE_UNITTEST #include <gtest.h> #endif #include <llvm/Support/DataTypes.h> #include <llvm/ADT/StringRef.h> #include <mcld/ADT/HashEntry.h> #include <mcld/ADT/HashTable.h> #include <mcld/ADT/StringHash.h> #include <mcld/LD/SectionData.h> #include <mcld/LD/LDSymbol.h> #include <mcld/Fragment/Stub.h> #include <string> namespace mcld { class Stub; class Relocation; /** \class BranchIsland * \brief BranchIsland is a collection of stubs * */ class BranchIsland { public: typedef SectionData::iterator iterator; typedef SectionData::const_iterator const_iterator; typedef std::vector<Relocation*> RelocationListType; typedef RelocationListType::iterator reloc_iterator; typedef RelocationListType::const_iterator const_reloc_iterator; public: /* * ---------- * --- Entry -> | Island | -> Exit --- * ---------- */ /// BranchIsland - constructor /// @param pEntryFrag - the entry fragment to the island /// @param pMaxSize - the max size the island can be /// @param pIndex - the inedx in the island factory BranchIsland(Fragment& pEntryFrag, size_t pMaxSize, size_t pIndex); ~BranchIsland(); /// fragment iterators of the island iterator begin(); const_iterator begin() const; iterator end(); const_iterator end() const; /// relocation iterators of the island reloc_iterator reloc_begin() { return m_Relocations.begin(); } const_reloc_iterator reloc_begin() const { return m_Relocations.begin(); } reloc_iterator reloc_end() { return m_Relocations.end(); } const_reloc_iterator reloc_end() const { return m_Relocations.end(); } /// observers uint64_t offset() const; size_t size() const; size_t maxSize() const; const std::string& name() const; size_t numOfStubs() const; /// findStub - return true if there is a stub built from the given prototype /// for the given relocation Stub* findStub(const Stub* pPrototype, const Relocation& pReloc); /// addStub - add a stub into the island bool addStub(const Stub* pPrototype, const Relocation& pReloc, Stub& pStub); /// addRelocation - add a relocation into island bool addRelocation(Relocation& pReloc); private: /** \class Key * \brief Key to recognize a stub in the island. * */ class Key { public: Key(const Stub* pPrototype, const LDSymbol* pSymbol, Stub::SWord pAddend) : m_pPrototype(pPrototype), m_pSymbol(pSymbol), m_Addend(pAddend) { } ~Key() { } const Stub* prototype() const { return m_pPrototype; } const LDSymbol* symbol() const { return m_pSymbol; } Stub::SWord addend() const { return m_Addend; } struct Hash { size_t operator() (const Key& KEY) const { llvm::StringRef sym_name(KEY.symbol()->name()); hash::StringHash<hash::ELF> str_hasher; return (size_t((uintptr_t)KEY.prototype())) ^ str_hasher(sym_name) ^ KEY.addend(); } }; struct Compare { bool operator() (const Key& KEY1, const Key& KEY2) const { return (KEY1.prototype() == KEY2.prototype()) && (KEY1.symbol() == KEY2.symbol()) && (KEY1.addend() == KEY2.addend()); } }; private: const Stub* m_pPrototype; const LDSymbol* m_pSymbol; Stub::SWord m_Addend; }; typedef HashEntry<Key, Stub*, Key::Compare> StubEntryType; typedef HashTable<StubEntryType, Key::Hash, EntryFactory<StubEntryType> > StubMapType; private: Fragment& m_Entry; // entry fragment of the island Fragment* m_pExit; // exit fragment of the island Fragment* m_pRear; // rear fragment of the island size_t m_MaxSize; std::string m_Name; StubMapType m_StubMap; /// m_Relocations - list of relocations created for stubs in this island RelocationListType m_Relocations; }; } // namespace of mcld #endif