//===- BranchIslandFactory.cpp --------------------------------------------===// // // The MCLinker Project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include #include #include #include #include using namespace mcld; //===----------------------------------------------------------------------===// // BranchIslandFactory //===----------------------------------------------------------------------===// /// ctor /// @param pMaxFwdBranchRange - the max forward branch range of the target /// @param pMaxBwdBranchRange - the max backward branch range of the target /// @param pMaxIslandSize - the predefined value for the max size of a island BranchIslandFactory::BranchIslandFactory(int64_t pMaxFwdBranchRange, int64_t pMaxBwdBranchRange, size_t pMaxIslandSize) : GCFactory(1u), // magic number m_MaxFwdBranchRange(pMaxFwdBranchRange - pMaxIslandSize), m_MaxBwdBranchRange(pMaxBwdBranchRange + pMaxIslandSize), m_MaxIslandSize(pMaxIslandSize) { } BranchIslandFactory::~BranchIslandFactory() { } /// group - group fragments and create islands when needed /// @param pSectionData - the SectionData holds fragments need to be grouped void BranchIslandFactory::group(Module& pModule) { /* FIXME: Currently only support relaxing .text section! */ LDSection* text = pModule.getSection(".text"); if (text != NULL && text->hasSectionData()) { SectionData& sd = *text->getSectionData(); uint64_t group_end = m_MaxFwdBranchRange; for (SectionData::iterator it = sd.begin(), ie = sd.end(); it != ie; ++it) { if ((*it).getOffset() + (*it).size() > group_end) { Fragment* frag = (*it).getPrevNode(); while (frag != NULL && frag->getKind() == Fragment::Alignment) { frag = frag->getPrevNode(); } if (frag != NULL) { produce(*frag); group_end = (*it).getOffset() + m_MaxFwdBranchRange; } } } if (getIslands(sd.back()).first == NULL) produce(sd.back()); } } /// produce - produce a island for the given fragment /// @param pFragment - the fragment needs a branch island BranchIsland* BranchIslandFactory::produce(Fragment& pFragment) { BranchIsland *island = allocate(); new (island) BranchIsland(pFragment, // entry fragment to the island m_MaxIslandSize, // the max size of the island size() - 1u); // index in the island factory return island; } /// getIsland - find fwd and bwd islands for the fragment /// @param pFragment - the fragment needs a branch island std::pair BranchIslandFactory::getIslands(const Fragment& pFragment) { BranchIsland* fwd = NULL; BranchIsland* bwd = NULL; for (iterator it = begin(), ie = end(), prev = ie; it != ie; prev = it, ++it) { if ((pFragment.getOffset() < (*it).offset()) && ((pFragment.getOffset() + m_MaxFwdBranchRange) >= (*it).offset())) { fwd = &*it; if (prev != ie) { int64_t bwd_off = (int64_t)pFragment.getOffset() + m_MaxBwdBranchRange; if ((pFragment.getOffset() > (*prev).offset()) && (bwd_off <= (int64_t) (*prev).offset())) { bwd = &*prev; } } break; } } return std::make_pair(fwd, bwd); }