176 lines
4.8 KiB
C++
176 lines
4.8 KiB
C++
//===- 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_BRANCHISLAND_H_
|
|
#define MCLD_LD_BRANCHISLAND_H_
|
|
|
|
#include "mcld/ADT/HashEntry.h"
|
|
#include "mcld/ADT/HashTable.h"
|
|
#include "mcld/ADT/StringHash.h"
|
|
#include "mcld/LD/SectionData.h"
|
|
#include "mcld/Fragment/FragmentRef.h"
|
|
#include "mcld/Fragment/Stub.h"
|
|
#include "mcld/LD/LDSymbol.h"
|
|
|
|
#include <llvm/Support/DataTypes.h>
|
|
#include <llvm/ADT/StringRef.h>
|
|
|
|
#include <string>
|
|
|
|
namespace mcld {
|
|
|
|
class Relocation;
|
|
class Stub;
|
|
|
|
/** \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
|
|
SectionData* getParent() const { return m_Entry.getParent(); }
|
|
|
|
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);
|
|
|
|
void addStub(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::DJB> 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 {
|
|
bool res = false;
|
|
if ((KEY1.prototype() == KEY2.prototype()) &&
|
|
(KEY1.addend() == KEY2.addend())) {
|
|
if (KEY1.symbol() == KEY2.symbol()) {
|
|
res = true;
|
|
} else {
|
|
// Folded symbols may use the existing stub.
|
|
if (KEY1.symbol()->hasFragRef() && KEY2.symbol()->hasFragRef()) {
|
|
const FragmentRef* ref1 = KEY1.symbol()->fragRef();
|
|
const FragmentRef* ref2 = KEY2.symbol()->fragRef();
|
|
if ((ref1->offset() == ref2->offset()) &&
|
|
(ref1->frag()->getOffset() == ref2->frag()->getOffset())) {
|
|
res = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
};
|
|
|
|
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
|
|
const 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 mcld
|
|
|
|
#endif // MCLD_LD_BRANCHISLAND_H_
|