BranchIslandFactory.cpp revision f33f6de54db174aa679a4b6d1e040d37e95541c0
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#include <mcld/Fragment/Fragment.h>
11#include <mcld/LD/LDSection.h>
12#include <mcld/LD/SectionData.h>
13#include <mcld/Module.h>
14
15using namespace mcld;
16
17//===----------------------------------------------------------------------===//
18// BranchIslandFactory
19//===----------------------------------------------------------------------===//
20
21/// ctor
22/// @param pMaxBranchRange - the max branch range of the target backend
23/// @param pMaxIslandSize - a predifned value (1KB here) to decide the max
24///                         size of the island
25BranchIslandFactory::BranchIslandFactory(uint64_t pMaxBranchRange,
26                                         uint64_t pMaxIslandSize)
27 : GCFactory<BranchIsland, 0>(1u), // magic number
28   m_MaxBranchRange(pMaxBranchRange - pMaxIslandSize),
29   m_MaxIslandSize(pMaxIslandSize)
30{
31}
32
33BranchIslandFactory::~BranchIslandFactory()
34{
35}
36
37/// group - group fragments and create islands when needed
38/// @param pSectionData - the SectionData holds fragments need to be grouped
39void BranchIslandFactory::group(Module& pModule)
40{
41  /* 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_MaxBranchRange - m_MaxIslandSize;
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_MaxBranchRange - m_MaxIslandSize;
55        }
56      }
57    }
58    if (find(sd.back()) == 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{
67  BranchIsland *island = allocate();
68  new (island) BranchIsland(pFragment,       // entry fragment to the island
69                            m_MaxIslandSize, // the max size of the island
70                            size() - 1u);    // index in the island factory
71  return island;
72}
73
74/// find - find a island for the given fragment
75/// @param pFragment - the fragment needs a branch isladn
76BranchIsland* BranchIslandFactory::find(const Fragment& pFragment)
77{
78  // Currently we always find the island in a forward direction.
79  // TODO: If we can search backward, then we may reduce the number of stubs.
80  for (iterator it = begin(), ie = end(); it != ie; ++it) {
81    if ((pFragment.getOffset() < (*it).offset()) &&
82        ((pFragment.getOffset() + m_MaxBranchRange) >= (*it).offset()))
83      return &(*it);
84  }
85  return NULL;
86}
87
88