mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-18 21:06:50 +00:00
Reland "[LLD][ELF] Don't spill to same memory region" (#130851)
Relands #129795 Remove skipped potential spills from their parent input section descriptions to prevent undefined behavior.
This commit is contained in:
parent
89fa592b68
commit
009dfb435f
@ -563,7 +563,7 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd,
|
||||
continue;
|
||||
|
||||
if (!cmd->matchesFile(*sec->file) || pat.excludesFile(*sec->file) ||
|
||||
sec->parent == &outCmd || !flagsMatch(sec))
|
||||
!flagsMatch(sec))
|
||||
continue;
|
||||
|
||||
if (sec->parent) {
|
||||
@ -626,7 +626,7 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd,
|
||||
|
||||
for (InputSectionDescription *isd : scd->sc.commands) {
|
||||
for (InputSectionBase *sec : isd->sectionBases) {
|
||||
if (sec->parent == &outCmd || !flagsMatch(sec))
|
||||
if (!flagsMatch(sec))
|
||||
continue;
|
||||
bool isSpill = sec->parent && isa<OutputSection>(sec->parent);
|
||||
if (!sec->parent || (isSpill && outCmd.name == "/DISCARD/")) {
|
||||
@ -1559,6 +1559,8 @@ bool LinkerScript::spillSections() {
|
||||
if (potentialSpillLists.empty())
|
||||
return false;
|
||||
|
||||
DenseSet<PotentialSpillSection *> skippedSpills;
|
||||
|
||||
bool spilled = false;
|
||||
for (SectionCommand *cmd : reverse(sectionCommands)) {
|
||||
auto *osd = dyn_cast<OutputDesc>(cmd);
|
||||
@ -1585,16 +1587,34 @@ bool LinkerScript::spillSections() {
|
||||
if (isa<PotentialSpillSection>(isec))
|
||||
continue;
|
||||
|
||||
// Find the next potential spill location and remove it from the list.
|
||||
auto it = potentialSpillLists.find(isec);
|
||||
if (it == potentialSpillLists.end())
|
||||
continue;
|
||||
break;
|
||||
|
||||
// Consume spills until finding one that might help, then consume it.
|
||||
auto canSpillHelp = [&](PotentialSpillSection *spill) {
|
||||
// Spills to the same region that overflowed cannot help.
|
||||
if (hasRegionOverflowed(osec->memRegion) &&
|
||||
spill->getParent()->memRegion == osec->memRegion)
|
||||
return false;
|
||||
if (hasRegionOverflowed(osec->lmaRegion) &&
|
||||
spill->getParent()->lmaRegion == osec->lmaRegion)
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
PotentialSpillList &list = it->second;
|
||||
PotentialSpillSection *spill = list.head;
|
||||
if (spill->next)
|
||||
PotentialSpillSection *spill;
|
||||
for (spill = list.head; spill; spill = spill->next) {
|
||||
if (list.head->next)
|
||||
list.head = spill->next;
|
||||
else
|
||||
potentialSpillLists.erase(isec);
|
||||
if (canSpillHelp(spill))
|
||||
break;
|
||||
skippedSpills.insert(spill);
|
||||
}
|
||||
if (!spill)
|
||||
continue;
|
||||
|
||||
// Replace the next spill location with the spilled section and adjust
|
||||
// its properties to match the new location. Note that the alignment of
|
||||
@ -1629,6 +1649,15 @@ bool LinkerScript::spillSections() {
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up any skipped spills.
|
||||
DenseSet<InputSectionDescription *> isds;
|
||||
for (PotentialSpillSection *s : skippedSpills)
|
||||
isds.insert(s->isd);
|
||||
for (InputSectionDescription *isd : isds)
|
||||
llvm::erase_if(isd->sections, [&](InputSection *s) {
|
||||
return skippedSpills.contains(dyn_cast<PotentialSpillSection>(s));
|
||||
});
|
||||
|
||||
return spilled;
|
||||
}
|
||||
|
||||
|
@ -450,3 +450,103 @@ SECTIONS {
|
||||
|
||||
# TO-DISCARD: error: section '.two_byte_section' cannot spill from/to /DISCARD/
|
||||
# TO-DISCARD-WARN: warning: section '.two_byte_section' cannot spill from/to /DISCARD/
|
||||
|
||||
#--- same-mem-region.lds
|
||||
## Spills to the same memory region that overflowed do not consume address assignment passes.
|
||||
MEMORY {
|
||||
a : ORIGIN = 0, LENGTH = 0
|
||||
b : ORIGIN = 0, LENGTH = 3
|
||||
c : ORIGIN = 3, LENGTH = 3
|
||||
d : ORIGIN = 6, LENGTH = 3
|
||||
}
|
||||
SECTIONS {
|
||||
CLASS(class) { *(.one_byte_section .two_byte_section) }
|
||||
.a00 : { CLASS(class) } >a AT>c
|
||||
.a01 : { CLASS(class) } >a AT>d
|
||||
.a02 : { CLASS(class) } >a AT>d
|
||||
.a03 : { CLASS(class) } >a AT>d
|
||||
.a04 : { CLASS(class) } >a AT>d
|
||||
.a05 : { CLASS(class) } >a AT>d
|
||||
.a06 : { CLASS(class) } >a AT>d
|
||||
.a07 : { CLASS(class) } >a AT>d
|
||||
.a08 : { CLASS(class) } >a AT>d
|
||||
.a09 : { CLASS(class) } >a AT>d
|
||||
.a10 : { CLASS(class) } >a AT>d
|
||||
.a11 : { CLASS(class) } >a AT>d
|
||||
.a12 : { CLASS(class) } >a AT>d
|
||||
.a13 : { CLASS(class) } >a AT>d
|
||||
.a14 : { CLASS(class) } >a AT>d
|
||||
.a15 : { CLASS(class) } >a AT>d
|
||||
.a16 : { CLASS(class) } >a AT>d
|
||||
.a17 : { CLASS(class) } >a AT>d
|
||||
.a18 : { CLASS(class) } >a AT>d
|
||||
.a19 : { CLASS(class) } >a AT>d
|
||||
.a20 : { CLASS(class) } >a AT>d
|
||||
.a21 : { CLASS(class) } >a AT>d
|
||||
.a22 : { CLASS(class) } >a AT>d
|
||||
.a23 : { CLASS(class) } >a AT>d
|
||||
.a24 : { CLASS(class) } >a AT>d
|
||||
.a25 : { CLASS(class) } >a AT>d
|
||||
.a26 : { CLASS(class) } >a AT>d
|
||||
.a27 : { CLASS(class) } >a AT>d
|
||||
.a28 : { CLASS(class) } >a AT>d
|
||||
.a29 : { CLASS(class) } >a AT>d
|
||||
.a30 : { CLASS(class) } >a AT>d
|
||||
.b : { CLASS(class) } >b AT>d
|
||||
}
|
||||
|
||||
# RUN: ld.lld -T same-mem-region.lds -o same-mem-region spill.o
|
||||
# RUN: llvm-readelf -S same-mem-region | FileCheck %s --check-prefix=SAME-MEM-REGION
|
||||
|
||||
# SAME-MEM-REGION: Name Type Address Off Size
|
||||
# SAME-MEM-REGION: .b PROGBITS 0000000000000000 001000 000003
|
||||
|
||||
#--- same-lma-region.lds
|
||||
## Spills to the same load region that overflowed do not consume address assignment passes.
|
||||
MEMORY {
|
||||
a : ORIGIN = 0, LENGTH = 0
|
||||
b : ORIGIN = 0, LENGTH = 3
|
||||
c : ORIGIN = 3, LENGTH = 3
|
||||
d : ORIGIN = 6, LENGTH = 3
|
||||
}
|
||||
SECTIONS {
|
||||
CLASS(class) { *(.one_byte_section .two_byte_section) }
|
||||
.a00 : { CLASS(class) } >c AT>a
|
||||
.a01 : { CLASS(class) } >d AT>a
|
||||
.a02 : { CLASS(class) } >d AT>a
|
||||
.a03 : { CLASS(class) } >d AT>a
|
||||
.a04 : { CLASS(class) } >d AT>a
|
||||
.a05 : { CLASS(class) } >d AT>a
|
||||
.a06 : { CLASS(class) } >d AT>a
|
||||
.a07 : { CLASS(class) } >d AT>a
|
||||
.a08 : { CLASS(class) } >d AT>a
|
||||
.a09 : { CLASS(class) } >d AT>a
|
||||
.a10 : { CLASS(class) } >d AT>a
|
||||
.a11 : { CLASS(class) } >d AT>a
|
||||
.a12 : { CLASS(class) } >d AT>a
|
||||
.a13 : { CLASS(class) } >d AT>a
|
||||
.a14 : { CLASS(class) } >d AT>a
|
||||
.a15 : { CLASS(class) } >d AT>a
|
||||
.a16 : { CLASS(class) } >d AT>a
|
||||
.a17 : { CLASS(class) } >d AT>a
|
||||
.a18 : { CLASS(class) } >d AT>a
|
||||
.a19 : { CLASS(class) } >d AT>a
|
||||
.a20 : { CLASS(class) } >d AT>a
|
||||
.a21 : { CLASS(class) } >d AT>a
|
||||
.a22 : { CLASS(class) } >d AT>a
|
||||
.a23 : { CLASS(class) } >d AT>a
|
||||
.a24 : { CLASS(class) } >d AT>a
|
||||
.a25 : { CLASS(class) } >d AT>a
|
||||
.a26 : { CLASS(class) } >d AT>a
|
||||
.a27 : { CLASS(class) } >d AT>a
|
||||
.a28 : { CLASS(class) } >d AT>a
|
||||
.a29 : { CLASS(class) } >d AT>a
|
||||
.a30 : { CLASS(class) } >d AT>a
|
||||
.b : { CLASS(class) } >d AT>b
|
||||
}
|
||||
|
||||
# RUN: ld.lld -T same-lma-region.lds -o same-lma-region spill.o
|
||||
# RUN: llvm-readelf -S same-lma-region | FileCheck %s --check-prefix=SAME-LMA-REGION
|
||||
|
||||
# SAME-LMA-REGION: Name Type Address Off Size
|
||||
# SAME-LMA-REGION: .b PROGBITS 0000000000000006 001006 000003
|
||||
|
Loading…
x
Reference in New Issue
Block a user