//===----------------------------------------------------------------------===// // Helper Functions //===----------------------------------------------------------------------===// /// compunteFragmentSize - compute the specific Fragment size uint64_t mcld::computeFragmentSize(const Layout& pLayout, const Fragment& pFrag) { switch (pFrag.getKind()) { case Fragment::Fillment: return static_cast<const FillFragment&>(pFrag).getSize(); case Fragment::Alignment: { uint64_t offset = pLayout.getOutputOffset(pFrag); const AlignFragment& align_frag = llvm::cast<AlignFragment>(pFrag); uint64_t size = llvm::OffsetToAlignment(offset, align_frag.getAlignment()); if (size > align_frag.getMaxBytesToEmit()) return 0; return size; } case Fragment::Region: return llvm::cast<RegionFragment>(pFrag).getRegion().size(); case Fragment::Target: return llvm::cast<TargetFragment>(pFrag).getSize(); case Fragment::Relocation: assert(0 && "the size of FT_Reloc fragment is handled by backend"); return 0; default: assert(0 && "invalid fragment kind"); return 0; } }
/// 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) { assert(NULL == find(pFragment)); uint64_t island_offset = pFragment.getOffset() + m_MaxBranchRange - (pFragment.getOffset() % m_MaxBranchRange); // find out the last fragment whose offset is smaller than the calculated // offset of the island Fragment* frag = &pFragment; while (NULL != frag->getNextNode()) { if (frag->getNextNode()->getOffset() > island_offset) break; frag = frag->getNextNode(); } // fall back one step if needed if (NULL != frag && (frag->getOffset() + frag->size()) > island_offset) frag = frag->getPrevNode(); // check not to break the alignment constraint in the target section // (i.e., do not insert the island after a Alignment fragment) while (NULL != frag && Fragment::Alignment == frag->getKind()) { frag = frag->getPrevNode(); } // can not find an entry fragment to bridge the island if (NULL == frag) return NULL; BranchIsland *island = allocate(); new (island) BranchIsland(*frag, // entry fragment to the island m_MaxIslandSize, // the max size of the island size() - 1u); // index in the island factory return island; }