Skip to content

Commit f7e8896

Browse files
committed
[LLD][ELF] Don't spill to same memory region
This prevents spills to the same memory region from causing spilling to take too many passes to converge. Handling this at spilling time allows us to relax the generation of spill sections; specifically, multiple spills can now be generated per output section. This should be fairly benign, and it would eventually allow allow linker scripts to express things like holes or minimum addresses for parts of output sections. The linker could then spill within an output section whenever address constraints are violated.
1 parent fa072bd commit f7e8896

File tree

2 files changed

+70
-9
lines changed

2 files changed

+70
-9
lines changed

lld/ELF/LinkerScript.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd,
563563
continue;
564564

565565
if (!cmd->matchesFile(*sec->file) || pat.excludesFile(*sec->file) ||
566-
sec->parent == &outCmd || !flagsMatch(sec))
566+
!flagsMatch(sec))
567567
continue;
568568

569569
if (sec->parent) {
@@ -626,7 +626,7 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd,
626626

627627
for (InputSectionDescription *isd : scd->sc.commands) {
628628
for (InputSectionBase *sec : isd->sectionBases) {
629-
if (sec->parent == &outCmd || !flagsMatch(sec))
629+
if (!flagsMatch(sec))
630630
continue;
631631
bool isSpill = sec->parent && isa<OutputSection>(sec->parent);
632632
if (!sec->parent || (isSpill && outCmd.name == "/DISCARD/")) {
@@ -1585,16 +1585,29 @@ bool LinkerScript::spillSections() {
15851585
if (isa<PotentialSpillSection>(isec))
15861586
continue;
15871587

1588-
// Find the next potential spill location and remove it from the list.
15891588
auto it = potentialSpillLists.find(isec);
15901589
if (it == potentialSpillLists.end())
1591-
continue;
1590+
break;
1591+
1592+
// Consume spills until finding one that might help, then consume it.
15921593
PotentialSpillList &list = it->second;
1593-
PotentialSpillSection *spill = list.head;
1594-
if (spill->next)
1595-
list.head = spill->next;
1596-
else
1597-
potentialSpillLists.erase(isec);
1594+
PotentialSpillSection *spill;
1595+
for (spill = list.head; spill; spill = spill->next) {
1596+
if (list.head->next)
1597+
list.head = spill->next;
1598+
else
1599+
potentialSpillLists.erase(isec);
1600+
1601+
// Spills to the same regions cannot help.
1602+
if (spill->getParent()->memRegion == osec->memRegion &&
1603+
spill->getParent()->lmaRegion == osec->lmaRegion)
1604+
continue;
1605+
1606+
// This spill might resolve the overflow.
1607+
break;
1608+
}
1609+
if (!spill)
1610+
continue;
15981611

15991612
// Replace the next spill location with the spilled section and adjust
16001613
// its properties to match the new location. Note that the alignment of

lld/test/ELF/linkerscript/section-class.test

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,3 +450,51 @@ SECTIONS {
450450

451451
# TO-DISCARD: error: section '.two_byte_section' cannot spill from/to /DISCARD/
452452
# TO-DISCARD-WARN: warning: section '.two_byte_section' cannot spill from/to /DISCARD/
453+
454+
#--- same-mem-region.lds
455+
## Spills to the same memory region do not consume address assignment passes.
456+
MEMORY {
457+
a : ORIGIN = 0, LENGTH = 0
458+
b : ORIGIN = 0, LENGTH = 3
459+
}
460+
SECTIONS {
461+
CLASS(class) { *(.one_byte_section .two_byte_section) }
462+
.a00 : { CLASS(class) } >a
463+
.a01 : { CLASS(class) } >a
464+
.a02 : { CLASS(class) } >a
465+
.a03 : { CLASS(class) } >a
466+
.a04 : { CLASS(class) } >a
467+
.a05 : { CLASS(class) } >a
468+
.a06 : { CLASS(class) } >a
469+
.a07 : { CLASS(class) } >a
470+
.a08 : { CLASS(class) } >a
471+
.a09 : { CLASS(class) } >a
472+
.a10 : { CLASS(class) } >a
473+
.a11 : { CLASS(class) } >a
474+
.a12 : { CLASS(class) } >a
475+
.a13 : { CLASS(class) } >a
476+
.a14 : { CLASS(class) } >a
477+
.a15 : { CLASS(class) } >a
478+
.a16 : { CLASS(class) } >a
479+
.a17 : { CLASS(class) } >a
480+
.a18 : { CLASS(class) } >a
481+
.a19 : { CLASS(class) } >a
482+
.a20 : { CLASS(class) } >a
483+
.a21 : { CLASS(class) } >a
484+
.a22 : { CLASS(class) } >a
485+
.a23 : { CLASS(class) } >a
486+
.a24 : { CLASS(class) } >a
487+
.a25 : { CLASS(class) } >a
488+
.a26 : { CLASS(class) } >a
489+
.a27 : { CLASS(class) } >a
490+
.a28 : { CLASS(class) } >a
491+
.a29 : { CLASS(class) } >a
492+
.a30 : { CLASS(class) } >a
493+
.b : { CLASS(class) } >b
494+
}
495+
496+
# RUN: ld.lld -T same-mem-region.lds -o same-mem-region spill.o
497+
# RUN: llvm-readelf -S same-mem-region | FileCheck %s --check-prefix=SAME-MEM-REGION
498+
499+
# SAME-MEM-REGION: Name Type Address Off Size
500+
# SAME-MEM-REGION: .b PROGBITS 0000000000000000 001000 000003

0 commit comments

Comments
 (0)