1 //===- BranchIsland.h -----------------------------------------------------===// 2 // 3 // The MCLinker Project 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 #ifndef MCLD_LD_BRANCHISLAND_H_ 10 #define MCLD_LD_BRANCHISLAND_H_ 11 12 #include "mcld/ADT/HashEntry.h" 13 #include "mcld/ADT/HashTable.h" 14 #include "mcld/ADT/StringHash.h" 15 #include "mcld/LD/SectionData.h" 16 #include "mcld/Fragment/FragmentRef.h" 17 #include "mcld/Fragment/Stub.h" 18 #include "mcld/LD/LDSymbol.h" 19 20 #include <llvm/Support/DataTypes.h> 21 #include <llvm/ADT/StringRef.h> 22 23 #include <string> 24 25 namespace mcld { 26 27 class Relocation; 28 class Stub; 29 30 /** \class BranchIsland 31 * \brief BranchIsland is a collection of stubs 32 * 33 */ 34 class BranchIsland { 35 public: 36 typedef SectionData::iterator iterator; 37 typedef SectionData::const_iterator const_iterator; 38 39 typedef std::vector<Relocation*> RelocationListType; 40 typedef RelocationListType::iterator reloc_iterator; 41 typedef RelocationListType::const_iterator const_reloc_iterator; 42 43 public: 44 /* 45 * ---------- 46 * --- Entry -> | Island | -> Exit --- 47 * ---------- 48 */ 49 50 /// BranchIsland - constructor 51 /// @param pEntryFrag - the entry fragment to the island 52 /// @param pMaxSize - the max size the island can be 53 /// @param pIndex - the inedx in the island factory 54 BranchIsland(Fragment& pEntryFrag, size_t pMaxSize, size_t pIndex); 55 56 ~BranchIsland(); 57 58 /// fragment iterators of the island 59 iterator begin(); 60 61 const_iterator begin() const; 62 63 iterator end(); 64 65 const_iterator end() const; 66 67 /// relocation iterators of the island reloc_begin()68 reloc_iterator reloc_begin() { return m_Relocations.begin(); } 69 reloc_begin()70 const_reloc_iterator reloc_begin() const { return m_Relocations.begin(); } 71 reloc_end()72 reloc_iterator reloc_end() { return m_Relocations.end(); } 73 reloc_end()74 const_reloc_iterator reloc_end() const { return m_Relocations.end(); } 75 76 /// observers 77 uint64_t offset() const; 78 79 size_t size() const; 80 81 size_t maxSize() const; 82 83 const std::string& name() const; 84 85 size_t numOfStubs() const; 86 87 /// findStub - return true if there is a stub built from the given prototype 88 /// for the given relocation 89 Stub* findStub(const Stub* pPrototype, const Relocation& pReloc); 90 91 /// addStub - add a stub into the island 92 bool addStub(const Stub* pPrototype, const Relocation& pReloc, Stub& pStub); 93 94 /// addRelocation - add a relocation into island 95 bool addRelocation(Relocation& pReloc); 96 97 private: 98 /** \class Key 99 * \brief Key to recognize a stub in the island. 100 * 101 */ 102 class Key { 103 public: Key(const Stub * pPrototype,const LDSymbol * pSymbol,Stub::SWord pAddend)104 Key(const Stub* pPrototype, const LDSymbol* pSymbol, Stub::SWord pAddend) 105 : m_pPrototype(pPrototype), m_pSymbol(pSymbol), m_Addend(pAddend) {} 106 ~Key()107 ~Key() {} 108 prototype()109 const Stub* prototype() const { return m_pPrototype; } 110 symbol()111 const LDSymbol* symbol() const { return m_pSymbol; } 112 addend()113 Stub::SWord addend() const { return m_Addend; } 114 115 struct Hash { operatorHash116 size_t operator()(const Key& KEY) const { 117 llvm::StringRef sym_name(KEY.symbol()->name()); 118 hash::StringHash<hash::DJB> str_hasher; 119 return (size_t((uintptr_t)KEY.prototype())) ^ str_hasher(sym_name) ^ 120 KEY.addend(); 121 } 122 }; 123 124 struct Compare { operatorCompare125 bool operator()(const Key& KEY1, const Key& KEY2) const { 126 bool res = false; 127 if ((KEY1.prototype() == KEY2.prototype()) && 128 (KEY1.addend() == KEY2.addend())) { 129 if (KEY1.symbol() == KEY2.symbol()) { 130 res = true; 131 } else { 132 // Folded symbols may use the existing stub. 133 if (KEY1.symbol()->hasFragRef() && KEY2.symbol()->hasFragRef()) { 134 const FragmentRef* ref1 = KEY1.symbol()->fragRef(); 135 const FragmentRef* ref2 = KEY2.symbol()->fragRef(); 136 if ((ref1->offset() == ref2->offset()) && 137 (ref1->frag()->getOffset() == ref2->frag()->getOffset())) { 138 res = true; 139 } 140 } 141 } 142 } 143 return res; 144 } 145 }; 146 147 private: 148 const Stub* m_pPrototype; 149 const LDSymbol* m_pSymbol; 150 Stub::SWord m_Addend; 151 }; 152 153 typedef HashEntry<Key, Stub*, Key::Compare> StubEntryType; 154 155 typedef HashTable<StubEntryType, Key::Hash, EntryFactory<StubEntryType> > 156 StubMapType; 157 158 private: 159 Fragment& m_Entry; // entry fragment of the island 160 Fragment* m_pExit; // exit fragment of the island 161 Fragment* m_pRear; // rear fragment of the island 162 size_t m_MaxSize; 163 std::string m_Name; 164 StubMapType m_StubMap; 165 /// m_Relocations - list of relocations created for stubs in this island 166 RelocationListType m_Relocations; 167 }; 168 169 } // namespace mcld 170 171 #endif // MCLD_LD_BRANCHISLAND_H_ 172