blob: 1e7ccdadc86e0975ea228e61bc3cc0198b23006c [file] [log] [blame]
//===- 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_