BranchIslandFactory.cpp revision 37b74a387bb3993387029859c2d9d051c41c724e
1//===- BranchIslandFactory.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/BranchIslandFactory.h"
10
11#include "mcld/Fragment/Fragment.h"
12#include "mcld/LD/LDSection.h"
13#include "mcld/LD/SectionData.h"
14#include "mcld/Module.h"
15
16namespace mcld {
17
18//===----------------------------------------------------------------------===//
19// BranchIslandFactory
20//===----------------------------------------------------------------------===//
21
22/// ctor
23/// @param pMaxFwdBranchRange - the max forward branch range of the target
24/// @param pMaxBwdBranchRange - the max backward branch range of the target
25/// @param pMaxIslandSize - the predefined value for the max size of a island
26BranchIslandFactory::BranchIslandFactory(int64_t pMaxFwdBranchRange,
27                                         int64_t pMaxBwdBranchRange,
28                                         size_t pMaxIslandSize)
29    : GCFactory<BranchIsland, 0>(1u),  // magic number
30      m_MaxFwdBranchRange(pMaxFwdBranchRange - pMaxIslandSize),
31      m_MaxBwdBranchRange(pMaxBwdBranchRange + pMaxIslandSize),
32      m_MaxIslandSize(pMaxIslandSize) {
33}
34
35BranchIslandFactory::~BranchIslandFactory() {
36}
37
38/// group - group fragments and create islands when needed
39/// @param pSectionData - the SectionData holds fragments need to be grouped
40void BranchIslandFactory::group(Module& pModule) {
41  /* FIXME: Currently only support relaxing .text section! */
42  LDSection* text = pModule.getSection(".text");
43  if (text != NULL && text->hasSectionData()) {
44    SectionData& sd = *text->getSectionData();
45    uint64_t group_end = m_MaxFwdBranchRange;
46    for (SectionData::iterator it = sd.begin(), ie = sd.end(); it != ie; ++it) {
47      if ((*it).getOffset() + (*it).size() > group_end) {
48        Fragment* frag = (*it).getPrevNode();
49        while (frag != NULL && frag->getKind() == Fragment::Alignment) {
50          frag = frag->getPrevNode();
51        }
52        if (frag != NULL) {
53          produce(*frag);
54          group_end = (*it).getOffset() + m_MaxFwdBranchRange;
55        }
56      }
57    }
58    if (getIslands(sd.back()).first == NULL)
59      produce(sd.back());
60  }
61}
62
63/// produce - produce a island for the given fragment
64/// @param pFragment - the fragment needs a branch island
65BranchIsland* BranchIslandFactory::produce(Fragment& pFragment) {
66  BranchIsland* island = allocate();
67  new (island) BranchIsland(pFragment,        // entry fragment to the island
68                            m_MaxIslandSize,  // the max size of the island
69                            size() - 1u);     // index in the island factory
70  return island;
71}
72
73/// getIsland - find fwd and bwd islands for the fragment
74/// @param pFragment - the fragment needs a branch island
75std::pair<BranchIsland*, BranchIsland*> BranchIslandFactory::getIslands(
76    const Fragment& pFragment) {
77  BranchIsland* fwd = NULL;
78  BranchIsland* bwd = NULL;
79  for (iterator it = begin(), ie = end(), prev = ie; it != ie;
80       prev = it, ++it) {
81    if ((pFragment.getOffset() < (*it).offset()) &&
82        ((pFragment.getOffset() + m_MaxFwdBranchRange) >= (*it).offset())) {
83      fwd = &*it;
84
85      if (prev != ie) {
86        int64_t bwd_off = (int64_t)pFragment.getOffset() + m_MaxBwdBranchRange;
87        if ((pFragment.getOffset() > (*prev).offset()) &&
88            (bwd_off <= (int64_t)(*prev).offset())) {
89          bwd = &*prev;
90        }
91      }
92      break;
93    }
94  }
95  return std::make_pair(fwd, bwd);
96}
97
98}  // namespace mcld
99