diff options
Diffstat (limited to 'lld/ELF/Writer.cpp')
| -rw-r--r-- | lld/ELF/Writer.cpp | 38 |
1 files changed, 28 insertions, 10 deletions
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 7bfe29eda695..705cc7bf9766 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1312,12 +1312,16 @@ static DenseMap<const InputSectionBase *, int> buildSectionOrder() { // Sorts the sections in ISD according to the provided section order. static void sortISDBySectionOrder(InputSectionDescription *isd, - const DenseMap<const InputSectionBase *, int> &order) { + const DenseMap<const InputSectionBase *, int> &order, + bool executableOutputSection) { SmallVector<InputSection *, 0> unorderedSections; SmallVector<std::pair<InputSection *, int>, 0> orderedSections; uint64_t unorderedSize = 0; + uint64_t totalSize = 0; for (InputSection *isec : isd->sections) { + if (executableOutputSection) + totalSize += isec->getSize(); auto i = order.find(isec); if (i == order.end()) { unorderedSections.push_back(isec); @@ -1355,8 +1359,15 @@ sortISDBySectionOrder(InputSectionDescription *isd, // of the second block of cold code can call the hot code without a thunk. So // we effectively double the amount of code that could potentially call into // the hot code without a thunk. + // + // The above is not necessary if total size of input sections in this "isd" + // is small. Note that we assume all input sections are executable if the + // output section is executable (which is not always true but supposed to + // cover most cases). size_t insPt = 0; - if (target->getThunkSectionSpacing() && !orderedSections.empty()) { + if (executableOutputSection && !orderedSections.empty() && + target->getThunkSectionSpacing() && + totalSize >= target->getThunkSectionSpacing()) { uint64_t unorderedPos = 0; for (; insPt != unorderedSections.size(); ++insPt) { unorderedPos += unorderedSections[insPt]->getSize(); @@ -1397,7 +1408,7 @@ static void sortSection(OutputSection &osec, if (!order.empty()) for (SectionCommand *b : osec.commands) if (auto *isd = dyn_cast<InputSectionDescription>(b)) - sortISDBySectionOrder(isd, order); + sortISDBySectionOrder(isd, order, osec.flags & SHF_EXECINSTR); if (script->hasSectionsCommand) return; @@ -1630,14 +1641,17 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() { if (config->emachine == EM_HEXAGON) hexagonTLSSymbolUpdate(outputSections); - int assignPasses = 0; + uint32_t pass = 0, assignPasses = 0; for (;;) { - bool changed = target->needsThunks && tc.createThunks(outputSections); + bool changed = target->needsThunks ? tc.createThunks(pass, outputSections) + : target->relaxOnce(pass); + ++pass; // With Thunk Size much smaller than branch range we expect to // converge quickly; if we get to 15 something has gone wrong. - if (changed && tc.pass >= 15) { - error("thunk creation not converged"); + if (changed && pass >= 15) { + error(target->needsThunks ? "thunk creation not converged" + : "relaxation not converged"); break; } @@ -1675,6 +1689,8 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() { } } } + if (!config->relocatable && config->emachine == EM_RISCV) + riscvFinalizeRelax(pass); if (config->relocatable) for (OutputSection *sec : outputSections) @@ -1741,6 +1757,7 @@ static void fixSymbolsAfterShrinking() { // option is used. template <class ELFT> void Writer<ELFT>::optimizeBasicBlockJumps() { assert(config->optimizeBBJumps); + SmallVector<InputSection *, 0> storage; script->assignAddresses(); // For every output section that has executable input sections, this @@ -1752,7 +1769,7 @@ template <class ELFT> void Writer<ELFT>::optimizeBasicBlockJumps() { for (OutputSection *osec : outputSections) { if (!(osec->flags & SHF_EXECINSTR)) continue; - SmallVector<InputSection *, 0> sections = getInputSections(*osec); + ArrayRef<InputSection *> sections = getInputSections(*osec, storage); size_t numDeleted = 0; // Delete all fall through jump instructions. Also, check if two // consecutive jump instructions can be flipped so that a fall @@ -1772,7 +1789,7 @@ template <class ELFT> void Writer<ELFT>::optimizeBasicBlockJumps() { fixSymbolsAfterShrinking(); for (OutputSection *osec : outputSections) - for (InputSection *is : getInputSections(*osec)) + for (InputSection *is : getInputSections(*osec, storage)) is->trim(); } @@ -2165,9 +2182,10 @@ template <class ELFT> void Writer<ELFT>::checkExecuteOnly() { if (!config->executeOnly) return; + SmallVector<InputSection *, 0> storage; for (OutputSection *osec : outputSections) if (osec->flags & SHF_EXECINSTR) - for (InputSection *isec : getInputSections(*osec)) + for (InputSection *isec : getInputSections(*osec, storage)) if (!(isec->flags & SHF_EXECINSTR)) error("cannot place " + toString(isec) + " into " + toString(osec->name) + |
