1//===- BranchIsland.cpp ---------------------------------------------------===//
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#include <mcld/LD/BranchIsland.h>
10#include <mcld/LD/ResolveInfo.h>
11#include <mcld/LD/LDSection.h>
12#include <mcld/Fragment/Stub.h>
13#include <mcld/Fragment/AlignFragment.h>
14
15#include <sstream>
16
17using namespace mcld;
18
19//==========================
20// BranchIsland
21
22BranchIsland::BranchIsland(Fragment& pEntryFrag,
23                           size_t pMaxSize,
24                           size_t pIndex)
25 : m_Entry(pEntryFrag),
26   m_pExit(pEntryFrag.getNextNode()),
27   m_pRear(NULL),
28   m_MaxSize(pMaxSize),
29   m_Name("island-")
30{
31  // island name
32  std::ostringstream index;
33  index << pIndex;
34  m_Name.append(index.str());
35}
36
37BranchIsland::~BranchIsland()
38{
39}
40
41/// fragment iterators of the island
42SectionData::iterator BranchIsland::begin()
43{
44  return ++iterator(&m_Entry);
45}
46
47SectionData::const_iterator BranchIsland::begin() const
48{
49  return ++iterator(&m_Entry);
50}
51
52SectionData::iterator BranchIsland::end()
53{
54  if (NULL != m_pExit)
55    return iterator(m_pExit);
56  return m_Entry.getParent()->end();
57}
58
59SectionData::const_iterator BranchIsland::end() const
60{
61  if (NULL != m_pExit)
62    return iterator(m_pExit);
63  return m_Entry.getParent()->end();
64}
65
66uint64_t BranchIsland::offset() const
67{
68  return m_Entry.getOffset() + m_Entry.size();
69}
70
71size_t BranchIsland::size() const
72{
73  size_t size = 0x0;
74  if (0x0 != numOfStubs()) {
75    size = m_pRear->getOffset() + m_pRear->size() -
76           m_Entry.getNextNode()->getOffset();
77  }
78  return size;
79}
80
81size_t BranchIsland::maxSize() const
82{
83  return m_MaxSize;
84}
85
86const std::string& BranchIsland::name() const
87{
88  return m_Name;
89}
90
91size_t BranchIsland::numOfStubs() const
92{
93  return m_StubMap.numOfEntries();
94}
95
96/// findStub - return true if there is a stub built from the given prototype
97///            for the given relocation
98Stub* BranchIsland::findStub(const Stub* pPrototype, const Relocation& pReloc)
99{
100  Key key(pPrototype, pReloc.symInfo()->outSymbol(), pReloc.addend());
101  StubMapType::iterator it = m_StubMap.find(key);
102  if (it != m_StubMap.end()) {
103    assert(NULL != it.getEntry()->value());
104    return it.getEntry()->value();
105  }
106  return NULL;
107}
108
109/// addStub - add a stub into the island
110bool BranchIsland::addStub(const Stub* pPrototype,
111                           const Relocation& pReloc,
112                           Stub& pStub)
113{
114  bool exist = false;
115  Key key(pPrototype, pReloc.symInfo()->outSymbol(), pReloc.addend());
116  StubEntryType* entry = m_StubMap.insert(key, exist);
117  if (!exist) {
118    entry->setValue(&pStub);
119    m_pRear = &pStub;
120    SectionData* sd = m_Entry.getParent();
121
122    // insert alignment fragment
123    // TODO: check if we can reduce this alignment fragment for some cases
124    AlignFragment* align_frag = new AlignFragment(pStub.alignment(),
125                                                  0x0,
126                                                  1u,
127                                                  pStub.alignment() - 1);
128    align_frag->setParent(sd);
129    sd->getFragmentList().insert(end(), align_frag);
130    align_frag->setOffset(align_frag->getPrevNode()->getOffset() +
131                          align_frag->getPrevNode()->size());
132
133    // insert stub fragment
134    pStub.setParent(sd);
135    sd->getFragmentList().insert(end(), &pStub);
136    pStub.setOffset(pStub.getPrevNode()->getOffset() +
137                    pStub.getPrevNode()->size());
138  }
139  return !exist;
140}
141
142/// addRelocation - add a relocation into island
143bool BranchIsland::addRelocation(Relocation& pReloc)
144{
145  m_Relocations.push_back(&pReloc);
146  return true;
147}
148
149