aboutsummaryrefslogtreecommitdiff
path: root/lld/ELF/Writer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/Writer.cpp')
-rw-r--r--lld/ELF/Writer.cpp38
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) +