[llvm-branch-commits] [lld] 7a5f2fb - Revert "[LLD] Implement --enable-non-contiguous-regions (#90007)"
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon May 13 10:38:13 PDT 2024
Author: Daniel Thornburgh
Date: 2024-05-13T10:38:10-07:00
New Revision: 7a5f2fb7a1326108258eb614e278810ee84d4bf6
URL: https://github.com/llvm/llvm-project/commit/7a5f2fb7a1326108258eb614e278810ee84d4bf6
DIFF: https://github.com/llvm/llvm-project/commit/7a5f2fb7a1326108258eb614e278810ee84d4bf6.diff
LOG: Revert "[LLD] Implement --enable-non-contiguous-regions (#90007)"
This reverts commit 673114447b66335268467396a073cdaaadd0b601.
Added:
Modified:
lld/ELF/Config.h
lld/ELF/Driver.cpp
lld/ELF/InputSection.cpp
lld/ELF/InputSection.h
lld/ELF/LinkerScript.cpp
lld/ELF/LinkerScript.h
lld/ELF/Options.td
lld/ELF/OutputSections.cpp
lld/ELF/OutputSections.h
lld/ELF/SyntheticSections.cpp
lld/ELF/SyntheticSections.h
lld/ELF/Writer.cpp
lld/docs/ELF/linker_script.rst
lld/docs/ReleaseNotes.rst
lld/docs/ld.lld.1
Removed:
lld/test/ELF/linkerscript/enable-non-contiguous-regions-arm-exidx.test
lld/test/ELF/linkerscript/enable-non-contiguous-regions.test
################################################################################
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index dbb81412453af..c55b547a733c7 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -238,7 +238,6 @@ struct Config {
bool emitLLVM;
bool emitRelocs;
bool enableNewDtags;
- bool enableNonContiguousRegions;
bool executeOnly;
bool exportDynamic;
bool fixCortexA53Errata843419;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 828499fa05a34..dd33f4bd772f2 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1250,8 +1250,6 @@ static void readConfigs(opt::InputArgList &args) {
config->emitRelocs = args.hasArg(OPT_emit_relocs);
config->enableNewDtags =
args.hasFlag(OPT_enable_new_dtags, OPT_disable_new_dtags, true);
- config->enableNonContiguousRegions =
- args.hasArg(OPT_enable_non_contiguous_regions);
config->entry = args.getLastArgValue(OPT_entry);
errorHandler().errorHandlingScript =
@@ -3087,7 +3085,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
// sectionBases.
for (SectionCommand *cmd : script->sectionCommands)
if (auto *osd = dyn_cast<OutputDesc>(cmd))
- osd->osec.finalizeInputSections(script.get());
+ osd->osec.finalizeInputSections();
}
// Two input sections with
diff erent output sections should not be folded.
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 2a1ccd997f8bc..fa81611e7c9e7 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -161,7 +161,6 @@ uint64_t SectionBase::getOffset(uint64_t offset) const {
}
case Regular:
case Synthetic:
- case Spill:
return cast<InputSection>(this)->outSecOff + offset;
case EHFrame: {
// Two code paths may reach here. First, clang_rt.crtbegin.o and GCC
@@ -310,12 +309,6 @@ std::string InputSectionBase::getObjMsg(uint64_t off) const {
.str();
}
-PotentialSpillSection::PotentialSpillSection(const InputSectionBase &source,
- InputSectionDescription &isd)
- : InputSection(source.file, source.flags, source.type, source.addralign, {},
- source.name, SectionBase::Spill),
- isd(&isd) {}
-
InputSection InputSection::discarded(nullptr, 0, 0, 0, ArrayRef<uint8_t>(), "");
InputSection::InputSection(InputFile *f, uint64_t flags, uint32_t type,
diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h
index 58e5306fd6dcd..1fb7077ca435b 100644
--- a/lld/ELF/InputSection.h
+++ b/lld/ELF/InputSection.h
@@ -48,7 +48,7 @@ template <class ELFT> struct RelsOrRelas {
// sections.
class SectionBase {
public:
- enum Kind { Regular, Synthetic, Spill, EHFrame, Merge, Output };
+ enum Kind { Regular, Synthetic, EHFrame, Merge, Output };
Kind kind() const { return (Kind)sectionKind; }
@@ -382,8 +382,7 @@ class InputSection : public InputSectionBase {
static bool classof(const SectionBase *s) {
return s->kind() == SectionBase::Regular ||
- s->kind() == SectionBase::Synthetic ||
- s->kind() == SectionBase::Spill;
+ s->kind() == SectionBase::Synthetic;
}
// Write this section to a mmap'ed file, assuming Buf is pointing to
@@ -426,26 +425,6 @@ class InputSection : public InputSectionBase {
template <class ELFT> void copyShtGroup(uint8_t *buf);
};
-// A marker for a potential spill location for another input section. This
-// broadly acts as if it were the original section until address assignment.
-// Then it is either replaced with the real input section or removed.
-class PotentialSpillSection : public InputSection {
-public:
- // The containing input section description; used to quickly replace this stub
- // with the actual section.
- InputSectionDescription *isd;
-
- // Next potential spill location for the same source input section.
- PotentialSpillSection *next = nullptr;
-
- PotentialSpillSection(const InputSectionBase &source,
- InputSectionDescription &isd);
-
- static bool classof(const SectionBase *sec) {
- return sec->kind() == InputSectionBase::Spill;
- }
-};
-
static_assert(sizeof(InputSection) <= 160, "InputSection is too big");
class SyntheticSection : public InputSection {
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 3ba59c112b8a8..c0a5014817b9c 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -304,9 +304,6 @@ getChangedSymbolAssignment(const SymbolAssignmentMap &oldValues) {
void LinkerScript::processInsertCommands() {
SmallVector<OutputDesc *, 0> moves;
for (const InsertCommand &cmd : insertCommands) {
- if (config->enableNonContiguousRegions)
- error("INSERT cannot be used with --enable-non-contiguous-regions");
-
for (StringRef name : cmd.names) {
// If base is empty, it may have been discarded by
// adjustOutputSections(). We do not handle such output sections.
@@ -489,12 +486,10 @@ static void sortInputSections(MutableArrayRef<InputSectionBase *> vec,
// Compute and remember which sections the InputSectionDescription matches.
SmallVector<InputSectionBase *, 0>
LinkerScript::computeInputSections(const InputSectionDescription *cmd,
- ArrayRef<InputSectionBase *> sections,
- const OutputSection &outCmd) {
+ ArrayRef<InputSectionBase *> sections) {
SmallVector<InputSectionBase *, 0> ret;
SmallVector<size_t, 0> indexes;
DenseSet<size_t> seen;
- DenseSet<InputSectionBase *> spills;
auto sortByPositionThenCommandLine = [&](size_t begin, size_t end) {
llvm::sort(MutableArrayRef<size_t>(indexes).slice(begin, end - begin));
for (size_t i = begin; i != end; ++i)
@@ -510,10 +505,10 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd,
size_t sizeBeforeCurrPat = ret.size();
for (size_t i = 0, e = sections.size(); i != e; ++i) {
- // Skip if the section is dead or has been matched by a previous pattern
- // in this input section description.
+ // Skip if the section is dead or has been matched by a previous input
+ // section description or a previous pattern.
InputSectionBase *sec = sections[i];
- if (!sec->isLive() || seen.contains(i))
+ if (!sec->isLive() || sec->parent || seen.contains(i))
continue;
// For --emit-relocs we have to ignore entries like
@@ -534,29 +529,6 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd,
(sec->flags & cmd->withoutFlags) != 0)
continue;
- if (sec->parent) {
- // Skip if not allowing multiple matches.
- if (!config->enableNonContiguousRegions)
- continue;
-
- // Disallow spilling into /DISCARD/; special handling would be needed
- // for this in address assignment, and the semantics are nebulous.
- if (outCmd.name == "/DISCARD/")
- continue;
-
- // Skip if the section's first match was /DISCARD/; such sections are
- // always discarded.
- if (sec->parent->name == "/DISCARD/")
- continue;
-
- // Skip if the section was already matched by a
diff erent input section
- // description within this output section.
- if (sec->parent == &outCmd)
- continue;
-
- spills.insert(sec);
- }
-
ret.push_back(sec);
indexes.push_back(i);
seen.insert(i);
@@ -583,30 +555,6 @@ LinkerScript::computeInputSections(const InputSectionDescription *cmd,
// Matched sections after the last SORT* are sorted by (--sort-alignment,
// input order).
sortByPositionThenCommandLine(sizeAfterPrevSort, ret.size());
-
- // The flag --enable-non-contiguous-regions may cause sections to match an
- // InputSectionDescription in more than one OutputSection. Matches after the
- // first were collected in the spills set, so replace these with potential
- // spill sections.
- if (!spills.empty()) {
- for (InputSectionBase *&sec : ret) {
- if (!spills.contains(sec))
- continue;
-
- // Append the spill input section to the list for the input section,
- // creating it if necessary.
- PotentialSpillSection *pss = make<PotentialSpillSection>(
- *sec, const_cast<InputSectionDescription &>(*cmd));
- auto [it, inserted] =
- potentialSpillLists.try_emplace(sec, PotentialSpillList{pss, pss});
- if (!inserted) {
- PotentialSpillSection *&tail = it->second.tail;
- tail = tail->next = pss;
- }
- sec = pss;
- }
- }
-
return ret;
}
@@ -629,7 +577,7 @@ void LinkerScript::discardSynthetic(OutputSection &outCmd) {
part.armExidx->exidxSections.end());
for (SectionCommand *cmd : outCmd.commands)
if (auto *isd = dyn_cast<InputSectionDescription>(cmd))
- for (InputSectionBase *s : computeInputSections(isd, secs, outCmd))
+ for (InputSectionBase *s : computeInputSections(isd, secs))
discard(*s);
}
}
@@ -640,7 +588,7 @@ LinkerScript::createInputSectionList(OutputSection &outCmd) {
for (SectionCommand *cmd : outCmd.commands) {
if (auto *isd = dyn_cast<InputSectionDescription>(cmd)) {
- isd->sectionBases = computeInputSections(isd, ctx.inputSections, outCmd);
+ isd->sectionBases = computeInputSections(isd, ctx.inputSections);
for (InputSectionBase *s : isd->sectionBases)
s->parent = &outCmd;
ret.insert(ret.end(), isd->sectionBases.begin(), isd->sectionBases.end());
@@ -696,9 +644,6 @@ void LinkerScript::processSectionCommands() {
// Process OVERWRITE_SECTIONS first so that it can overwrite the main script
// or orphans.
- if (config->enableNonContiguousRegions && !overwriteSections.empty())
- error("OVERWRITE_SECTIONS cannot be used with "
- "--enable-non-contiguous-regions");
DenseMap<CachedHashStringRef, OutputDesc *> map;
size_t i = 0;
for (OutputDesc *osd : overwriteSections) {
@@ -1121,12 +1066,8 @@ void LinkerScript::assignOffsets(OutputSection *sec) {
// Handle a single input section description command.
// It calculates and assigns the offsets for each section and also
// updates the output section size.
-
- auto §ions = cast<InputSectionDescription>(cmd)->sections;
- for (InputSection *isec : sections) {
+ for (InputSection *isec : cast<InputSectionDescription>(cmd)->sections) {
assert(isec->getParent() == sec);
- if (isa<PotentialSpillSection>(isec))
- continue;
const uint64_t pos = dot;
dot = alignToPowerOf2(dot, isec->addralign);
isec->outSecOff = dot - sec->addr;
@@ -1423,114 +1364,6 @@ const Defined *LinkerScript::assignAddresses() {
return getChangedSymbolAssignment(oldValues);
}
-static bool hasRegionOverflowed(MemoryRegion *mr) {
- if (!mr)
- return false;
- return mr->curPos - mr->getOrigin() > mr->getLength();
-}
-
-// Spill input sections in reverse order of address assignment to (potentially)
-// bring memory regions out of overflow. The size savings of a spill can only be
-// estimated, since general linker script arithmetic may occur afterwards.
-// Under-estimates may cause unnecessary spills, but over-estimates can always
-// be corrected on the next pass.
-bool LinkerScript::spillSections() {
- if (!config->enableNonContiguousRegions)
- return false;
-
- bool spilled = false;
- for (SectionCommand *cmd : reverse(sectionCommands)) {
- auto *od = dyn_cast<OutputDesc>(cmd);
- if (!od)
- continue;
- OutputSection *osec = &od->osec;
- if (!osec->memRegion)
- continue;
-
- // Input sections that have replaced a potential spill and should be removed
- // from their input section description.
- DenseSet<InputSection *> spilledInputSections;
-
- for (SectionCommand *cmd : reverse(osec->commands)) {
- if (!hasRegionOverflowed(osec->memRegion) &&
- !hasRegionOverflowed(osec->lmaRegion))
- break;
-
- auto *isd = dyn_cast<InputSectionDescription>(cmd);
- if (!isd)
- continue;
- for (InputSection *isec : reverse(isd->sections)) {
- // Potential spill locations cannot be spilled.
- 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;
- PotentialSpillList &list = it->second;
- PotentialSpillSection *spill = list.head;
- if (spill->next)
- list.head = spill->next;
- else
- potentialSpillLists.erase(isec);
-
- // Replace the next spill location with the spilled section and adjust
- // its properties to match the new location. Note that the alignment of
- // the spill section may have diverged from the original due to e.g. a
- // SUBALIGN. Correct assignment requires the spill's alignment to be
- // used, not the original.
- spilledInputSections.insert(isec);
- *llvm::find(spill->isd->sections, spill) = isec;
- isec->parent = spill->parent;
- isec->addralign = spill->addralign;
-
- // Record the (potential) reduction in the region's end position.
- osec->memRegion->curPos -= isec->getSize();
- if (osec->lmaRegion)
- osec->lmaRegion->curPos -= isec->getSize();
-
- // Spilling continues until the end position no longer overflows the
- // region. Then, another round of address assignment will either confirm
- // the spill's success or lead to yet more spilling.
- if (!hasRegionOverflowed(osec->memRegion) &&
- !hasRegionOverflowed(osec->lmaRegion))
- break;
- }
-
- // Remove any spilled input sections to complete their move.
- if (!spilledInputSections.empty()) {
- spilled = true;
- llvm::erase_if(isd->sections, [&](InputSection *isec) {
- return spilledInputSections.contains(isec);
- });
- }
- }
- }
-
- return spilled;
-}
-
-// Erase any potential spill sections that were not used.
-void LinkerScript::erasePotentialSpillSections() {
- if (potentialSpillLists.empty())
- return;
-
- // Collect the set of input section descriptions that contain potential
- // spills.
- DenseSet<InputSectionDescription *> isds;
- for (const auto &[_, list] : potentialSpillLists)
- for (PotentialSpillSection *s = list.head; s; s = s->next)
- isds.insert(s->isd);
-
- for (InputSectionDescription *isd : isds)
- llvm::erase_if(isd->sections, [](InputSection *s) {
- return isa<PotentialSpillSection>(s);
- });
-
- potentialSpillLists.clear();
-}
-
// Creates program headers as instructed by PHDRS linker script command.
SmallVector<PhdrEntry *, 0> LinkerScript::createPhdrs() {
SmallVector<PhdrEntry *, 0> ret;
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index 734d4e7498aa2..b09cd12c46f99 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -10,7 +10,6 @@
#define LLD_ELF_LINKER_SCRIPT_H
#include "Config.h"
-#include "InputSection.h"
#include "Writer.h"
#include "lld/Common/LLVM.h"
#include "lld/Common/Strings.h"
@@ -288,8 +287,7 @@ class LinkerScript final {
SmallVector<InputSectionBase *, 0>
computeInputSections(const InputSectionDescription *,
- ArrayRef<InputSectionBase *>,
- const OutputSection &outCmd);
+ ArrayRef<InputSectionBase *>);
SmallVector<InputSectionBase *, 0> createInputSectionList(OutputSection &cmd);
@@ -335,8 +333,6 @@ class LinkerScript final {
bool shouldKeep(InputSectionBase *s);
const Defined *assignAddresses();
- bool spillSections();
- void erasePotentialSpillSections();
void allocateHeaders(SmallVector<PhdrEntry *, 0> &phdrs);
void processSectionCommands();
void processSymbolAssignments();
@@ -404,15 +400,6 @@ class LinkerScript final {
//
// then provideMap should contain the mapping: 'v' -> ['a', 'b', 'c']
llvm::MapVector<StringRef, SmallVector<StringRef, 0>> provideMap;
-
- // List of potential spill locations (PotentialSpillSection) for an input
- // section.
- struct PotentialSpillList {
- // Never nullptr.
- PotentialSpillSection *head;
- PotentialSpillSection *tail;
- };
- llvm::DenseMap<InputSectionBase *, PotentialSpillList> potentialSpillLists;
};
struct ScriptWrapper {
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index 883a6079bf507..b9e05a4b1fd5c 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -197,9 +197,6 @@ def emit_relocs: F<"emit-relocs">, HelpText<"Generate relocations in output">;
def enable_new_dtags: F<"enable-new-dtags">,
HelpText<"Enable new dynamic tags (default)">;
-def enable_non_contiguous_regions : FF<"enable-non-contiguous-regions">,
- HelpText<"Spill input sections to later matching output sections to avoid memory region overflow">;
-
def end_group: F<"end-group">,
HelpText<"Ignored for compatibility with GNU unless you pass --warn-backrefs">;
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index fcb4c4387aa97..9c667241360f6 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -186,7 +186,7 @@ static MergeSyntheticSection *createMergeSynthetic(StringRef name,
// new synthetic sections at the location of the first input section
// that it replaces. It then finalizes each synthetic section in order
// to compute an output offset for each piece of each input section.
-void OutputSection::finalizeInputSections(LinkerScript *script) {
+void OutputSection::finalizeInputSections() {
std::vector<MergeSyntheticSection *> mergeSections;
for (SectionCommand *cmd : commands) {
auto *isd = dyn_cast<InputSectionDescription>(cmd);
@@ -226,11 +226,6 @@ void OutputSection::finalizeInputSections(LinkerScript *script) {
i = std::prev(mergeSections.end());
syn->entsize = ms->entsize;
isd->sections.push_back(syn);
- // The merge synthetic section inherits the potential spill locations of
- // its first contained section.
- auto it = script->potentialSpillLists.find(ms);
- if (it != script->potentialSpillLists.end())
- script->potentialSpillLists.try_emplace(syn, it->second);
}
(*i)->addSection(ms);
}
diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h
index 78fede48a23f2..421a0181feb5d 100644
--- a/lld/ELF/OutputSections.h
+++ b/lld/ELF/OutputSections.h
@@ -75,7 +75,7 @@ class OutputSection final : public SectionBase {
void recordSection(InputSectionBase *isec);
void commitSection(InputSection *isec);
- void finalizeInputSections(LinkerScript *script = nullptr);
+ void finalizeInputSections();
// The following members are normally only used in linker scripts.
MemoryRegion *memRegion = nullptr;
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 298c714adb3b4..7b9ada40c0f67 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -4074,13 +4074,6 @@ static bool isDuplicateArmExidxSec(InputSection *prev, InputSection *cur) {
// InputSection with the highest address and any InputSections that have
// mergeable .ARM.exidx table entries are removed from it.
void ARMExidxSyntheticSection::finalizeContents() {
- // Ensure that any fixed-point iterations after the first see the original set
- // of sections.
- if (!originalExecutableSections.empty())
- executableSections = originalExecutableSections;
- else if (config->enableNonContiguousRegions)
- originalExecutableSections = executableSections;
-
// The executableSections and exidxSections that we use to derive the final
// contents of this SyntheticSection are populated before
// processSectionCommands() and ICF. A /DISCARD/ entry in SECTIONS command or
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 34949025a45f7..995fd4b344b07 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -1255,10 +1255,6 @@ class ARMExidxSyntheticSection : public SyntheticSection {
// either find the .ARM.exidx section or know that we need to generate one.
SmallVector<InputSection *, 0> executableSections;
- // Value of executableSecitons before finalizeContents(), so that it can be
- // run repeateadly during fixed point iteration.
- SmallVector<InputSection *, 0> originalExecutableSections;
-
// The executable InputSection with the highest address to use for the
// sentinel. We store separately from ExecutableSections as merging of
// duplicate entries may mean this InputSection is removed from
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 8d529f2bdb9f9..e400ed2ae945b 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1403,18 +1403,13 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
AArch64Err843419Patcher a64p;
ARMErr657417Patcher a32p;
script->assignAddresses();
-
// .ARM.exidx and SHF_LINK_ORDER do not require precise addresses, but they
// do require the relative addresses of OutputSections because linker scripts
// can assign Virtual Addresses to OutputSections that are not monotonically
- // increasing. Anything here must be repeatable, since spilling may change
- // section order.
- const auto finalizeOrderDependentContent = [this] {
- for (Partition &part : partitions)
- finalizeSynthetic(part.armExidx.get());
- resolveShfLinkOrder();
- };
- finalizeOrderDependentContent();
+ // increasing.
+ for (Partition &part : partitions)
+ finalizeSynthetic(part.armExidx.get());
+ resolveShfLinkOrder();
// Converts call x at GDPLT to call __tls_get_addr
if (config->emachine == EM_HEXAGON)
@@ -1424,8 +1419,6 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
for (;;) {
bool changed = target->needsThunks ? tc.createThunks(pass, outputSections)
: target->relaxOnce(pass);
- bool spilled = script->spillSections();
- changed |= spilled;
++pass;
// With Thunk Size much smaller than branch range we expect to
@@ -1471,9 +1464,6 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
" does not converge");
break;
}
- } else if (spilled) {
- // Spilling can change relative section order.
- finalizeOrderDependentContent();
}
}
if (!config->relocatable)
@@ -1493,10 +1483,6 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
osec->name + " is not a multiple of alignment (" +
Twine(osec->addralign) + ")");
}
-
- // Sizes are no longer allowed to grow, so all allowable spills have been
- // taken. Remove any leftover potential spills.
- script->erasePotentialSpillSections();
}
// If Input Sections have been shrunk (basic block sections) then
diff --git a/lld/docs/ELF/linker_script.rst b/lld/docs/ELF/linker_script.rst
index 7a35534be096c..3606ef4fe4b8e 100644
--- a/lld/docs/ELF/linker_script.rst
+++ b/lld/docs/ELF/linker_script.rst
@@ -197,14 +197,3 @@ the current location to a max-page-size boundary, ensuring that the next
LLD will insert ``.relro_padding`` immediately before the symbol assignment
using ``DATA_SEGMENT_RELRO_END``.
-
-Non-contiguous regions
-~~~~~~~~~~~~~~~~~~~~~~
-
-The flag ``--enable-non-contiguous-regions`` allows input sections to spill to
-later matches rather than causing the link to fail by overflowing a memory
-region. Unlike GNU ld, ``/DISCARD/`` only matches previously-unmatched sections
-(i.e., the flag does not affect it). Also, if a section fails to fit at any of
-its matches, the link fails instead of discarding the section. Accordingly, the
-GNU flag ``--enable-non-contiguous-regions-warnings`` is not implemented, as it
-exists to warn about such occurrences.
diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst
index e7a913e025da9..f8fdebfeaecf2 100644
--- a/lld/docs/ReleaseNotes.rst
+++ b/lld/docs/ReleaseNotes.rst
@@ -38,12 +38,6 @@ ELF Improvements
* ``--debug-names`` is added to create a merged ``.debug_names`` index
from input ``.debug_names`` sections. Type units are not handled yet.
(`#86508 <https://github.com/llvm/llvm-project/pull/86508>`_)
-* ``--enable-non-contiguous-regions`` option allows automatically packing input
- sections into memory regions by automatically spilling to later matches if a
- region would overflow. This reduces the toil of manually packing regions
- (typical for embedded). It also makes full LTO feasible in such cases, since
- IR merging currently prevents the linker script from referring to input
- files. (`#90007 <https://github.com/llvm/llvm-project/pull/90007>`_)
Breaking changes
----------------
diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1
index 0df13f07f560d..9ea1a9c52f2a1 100644
--- a/lld/docs/ld.lld.1
+++ b/lld/docs/ld.lld.1
@@ -222,8 +222,6 @@ segment header.
Generate relocations in the output.
.It Fl -enable-new-dtags
Enable new dynamic tags.
-.It Fl -enable-non-contiguous-regions
-Spill input sections to later matching output sections to avoid memory region overflow.
.It Fl -end-lib
End a grouping of objects that should be treated as if they were together
in an archive.
diff --git a/lld/test/ELF/linkerscript/enable-non-contiguous-regions-arm-exidx.test b/lld/test/ELF/linkerscript/enable-non-contiguous-regions-arm-exidx.test
deleted file mode 100644
index 3f7b9c4e5f8b8..0000000000000
--- a/lld/test/ELF/linkerscript/enable-non-contiguous-regions-arm-exidx.test
+++ /dev/null
@@ -1,55 +0,0 @@
-## When spilling reorders input sections, the .ARM.exidx table is rebuilt using
-## the new order.
-
-# REQUIRES: arm
-# RUN: rm -rf %t && split-file %s %t && cd %t
-# RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi test.s -o test.o
-# RUN: ld.lld -T test.ld test.o -o test --enable-non-contiguous-regions
-# RUN: llvm-readobj -x .ARM.exidx test | FileCheck %s
-
-# CHECK: 20000000 08849780 1c000000 10849880
-# CHECK-NEXT: 1c000000 01000000
-
-#--- test.ld
-MEMORY {
- exidx : ORIGIN = 0, LENGTH = 32
- a : ORIGIN = 32, LENGTH = 4
- b : ORIGIN = 36, LENGTH = 4
- c : ORIGIN = 40, LENGTH = 4
-}
-
-SECTIONS {
- .ARM.exidx : { *(.ARM.exidx) } >exidx
- .first_chance : { *(.text .text.f2) } >a
- .text.f1 : { *(.text.f1) } >b
- .last_chance : { *(.text.f2) } >c
-}
-
-#--- test.s
- .syntax unified
- .section .text, "ax",%progbits
- .globl _start
-_start:
- .fnstart
- bx lr
- .save {r7, lr}
- .setfp r7, sp, #0
- .fnend
-
- .section .text.f1, "ax", %progbits
- .globl f1
-f1:
- .fnstart
- bx lr
- .save {r8, lr}
- .setfp r8, sp, #0
- .fnend
-
- .section .text.f2, "ax", %progbits
- .globl f2
-f2:
- .fnstart
- bx lr
- .save {r8, lr}
- .setfp r8, sp, #0
- .fnend
diff --git a/lld/test/ELF/linkerscript/enable-non-contiguous-regions.test b/lld/test/ELF/linkerscript/enable-non-contiguous-regions.test
deleted file mode 100644
index 392106fd476fd..0000000000000
--- a/lld/test/ELF/linkerscript/enable-non-contiguous-regions.test
+++ /dev/null
@@ -1,265 +0,0 @@
-# REQUIRES: x86
-
-# RUN: rm -rf %t && split-file %s %t && cd %t
-# RUN: llvm-mc -n -filetype=obj -triple=x86_64 spill.s -o spill.o
-
-## An input section spills to a later match when the region of its first match
-## would overflow. The spill uses the alignment of the later match.
-
-# RUN: ld.lld -T spill.ld spill.o -o spill --enable-non-contiguous-regions
-# RUN: llvm-readelf -S spill | FileCheck %s --check-prefix=SPILL
-
-# SPILL: Name Type Address Off Size
-# SPILL: .first_chance PROGBITS 0000000000000000 001000 000001
-# SPILL-NEXT: .last_chance PROGBITS 0000000000000008 001008 000002
-
-## A spill off the end still fails the link.
-
-# RUN: not ld.lld -T spill-fail.ld spill.o --enable-non-contiguous-regions 2>&1 |\
-# RUN: FileCheck %s --check-prefix=SPILL-FAIL --implicit-check-not=error:
-
-# SPILL-FAIL: error: section '.last_chance' will not fit in region 'b': overflowed by 2 bytes
-
-## The above spill still occurs when the LMA would overflow, even though the
-## VMA would fit.
-
-# RUN: ld.lld -T spill-lma.ld spill.o -o spill-lma --enable-non-contiguous-regions
-# RUN: llvm-readelf -S spill-lma | FileCheck %s --check-prefix=SPILL-LMA
-
-# SPILL-LMA: Name Type Address Off Size
-# SPILL-LMA: .first_chance PROGBITS 0000000000000000 001000 000001
-# SPILL-LMA-NEXT: .last_chance PROGBITS 0000000000000003 001003 000002
-
-## A spill occurs to an additional match after the first.
-
-# RUN: ld.lld -T spill-later.ld spill.o -o spill-later --enable-non-contiguous-regions
-# RUN: llvm-readelf -S spill-later | FileCheck %s --check-prefix=SPILL-LATER
-
-# SPILL-LATER: Name Type Address Off Size
-# SPILL-LATER: .first_chance PROGBITS 0000000000000000 001000 000001
-# SPILL-LATER-NEXT: .second_chance PROGBITS 0000000000000002 001001 000000
-# SPILL-LATER-NEXT: .last_chance PROGBITS 0000000000000003 001003 000002
-
-## A later overflow causes an earlier section to spill.
-
-# RUN: ld.lld -T spill-earlier.ld spill.o -o spill-earlier --enable-non-contiguous-regions
-# RUN: llvm-readelf -S spill-earlier | FileCheck %s --check-prefix=SPILL-EARLIER
-
-# SPILL-EARLIER: Name Type Address Off Size
-# SPILL-EARLIER: .first_chance PROGBITS 0000000000000000 001000 000002
-# SPILL-EARLIER-NEXT: .last_chance PROGBITS 0000000000000002 001002 000001
-
-## An additional match in /DISCARD/ has no effect.
-
-# RUN: not ld.lld -T no-spill-into-discard.ld spill.o --enable-non-contiguous-regions 2>&1 |\
-# RUN: FileCheck %s --check-prefix=NO-SPILL-INTO-DISCARD --implicit-check-not=error:
-
-# NO-SPILL-INTO-DISCARD: error: section '.osec' will not fit in region 'a': overflowed by 1 bytes
-
-## An additional match after /DISCARD/ has no effect.
-
-# RUN: ld.lld -T no-spill-from-discard.ld spill.o -o no-spill-from-discard --enable-non-contiguous-regions
-# RUN: llvm-readelf -S no-spill-from-discard | FileCheck %s --check-prefix=NO-SPILL-FROM-DISCARD
-
-# NO-SPILL-FROM-DISCARD: Name Type Address Off Size
-# NO-SPILL-FROM-DISCARD-NOT: .osec
-
-## SHF_MERGEd sections are spilled according to the matches of the first merged
-## input section (the one giving the resulting section its name).
-
-# RUN: llvm-mc -n -filetype=obj -triple=x86_64 merge.s -o merge.o
-# RUN: ld.lld -T spill-merge.ld merge.o -o spill-merge --enable-non-contiguous-regions
-# RUN: llvm-readelf -S spill-merge | FileCheck %s --check-prefix=SPILL-MERGE
-
-# SPILL-MERGE: Name Type Address Off Size
-# SPILL-MERGE: .first PROGBITS 0000000000000000 000190 000000
-# SPILL-MERGE-NEXT: .second PROGBITS 0000000000000001 001001 000002
-# SPILL-MERGE-NEXT: .third PROGBITS 0000000000000003 001003 000000
-
-## An error is reported for INSERT.
-
-# RUN: not ld.lld -T insert.ld spill.o --enable-non-contiguous-regions 2>&1 |\
-# RUN: FileCheck %s --check-prefix=INSERT
-
-# INSERT: error: INSERT cannot be used with --enable-non-contiguous-regions
-
-## An error is reported for OVERWRITE_SECTIONS.
-
-# RUN: not ld.lld -T overwrite-sections.ld spill.o --enable-non-contiguous-regions 2>&1 |\
-# RUN: FileCheck %s --check-prefix=OVERWRITE_SECTIONS
-
-# OVERWRITE_SECTIONS: error: OVERWRITE_SECTIONS cannot be used with --enable-non-contiguous-regions
-
-## SHF_LINK_ORDER is reordered when spilling changes relative section order.
-
-# RUN: llvm-mc -n -filetype=obj -triple=x86_64 link-order.s -o link-order.o
-# RUN: ld.lld -T link-order.ld link-order.o -o link-order --enable-non-contiguous-regions
-# RUN: llvm-readobj -x .order link-order | FileCheck %s --check-prefix=LINK-ORDER
-
-# LINK-ORDER: 020301
-
-#--- spill.s
-.section .one_byte_section,"a", at progbits
-.fill 1
-
-.section .two_byte_section,"a", at progbits
-.fill 2
-
-#--- spill.ld
-MEMORY {
- a : ORIGIN = 0, LENGTH = 2
- b : ORIGIN = 2, LENGTH = 16
-}
-
-SECTIONS {
- .first_chance : SUBALIGN(1) { *(.one_byte_section) *(.two_byte_section) } >a
- .last_chance : SUBALIGN(8) { *(.two_byte_section) } >b
-}
-
-#--- spill-fail.ld
-MEMORY {
- a : ORIGIN = 0, LENGTH = 1
- b : ORIGIN = 2, LENGTH = 0
-}
-
-SECTIONS {
- .first_chance : { *(.one_byte_section) *(.two_byte_section) } >a
- .last_chance : { *(.two_byte_section) } >b
-}
-
-#--- spill-lma.ld
-MEMORY {
- vma_a : ORIGIN = 0, LENGTH = 3
- vma_b : ORIGIN = 3, LENGTH = 3
- lma_a : ORIGIN = 6, LENGTH = 2
- lma_b : ORIGIN = 8, LENGTH = 2
-}
-
-SECTIONS {
- .first_chance : { *(.one_byte_section) *(.two_byte_section) } >vma_a AT>lma_a
- .last_chance : { *(.two_byte_section) } >vma_b AT>lma_b
-}
-
-#--- spill-later.ld
-MEMORY {
- a : ORIGIN = 0, LENGTH = 2
- b : ORIGIN = 2, LENGTH = 1
- c : ORIGIN = 3, LENGTH = 2
-}
-
-SECTIONS {
- .first_chance : { *(.one_byte_section) *(.two_byte_section) } >a
- .second_chance : { *(.two_byte_section) } >b
- .last_chance : { *(.two_byte_section) } >c
-}
-
-#--- spill-earlier.ld
-MEMORY {
- a : ORIGIN = 0, LENGTH = 2
- b : ORIGIN = 2, LENGTH = 1
-}
-
-SECTIONS {
- .first_chance : { *(.one_byte_section) *(.two_byte_section) } >a
- .last_chance : { *(.one_byte_section) } >b
-}
-
-#--- no-spill-into-discard.ld
-MEMORY {
- a : ORIGIN = 0, LENGTH = 1
-}
-
-SECTIONS {
- .osec : { *(.two_byte_section) } >a
- /DISCARD/ : { *(.one_byte_section) *(.two_byte_section) }
-}
-
-#--- no-spill-from-discard.ld
-MEMORY {
- a : ORIGIN = 0, LENGTH = 2
-}
-
-SECTIONS {
- /DISCARD/ : { *(.one_byte_section) *(.two_byte_section) }
- .osec : { *(.two_byte_section) } >a
-}
-
-#--- merge.s
-.section .a,"aM", at progbits,1
-.byte 0x12, 0x34
-
-.section .b,"aM", at progbits,1
-.byte 0x12
-
-#--- spill-merge.ld
-MEMORY {
- a : ORIGIN = 0, LENGTH = 1
- b : ORIGIN = 1, LENGTH = 2
- c : ORIGIN = 3, LENGTH = 2
-}
-
-SECTIONS {
- .first : { *(.a) *(.b) } >a
- .second : { *(.a) } >b
- .third : { *(.b) } >c
-}
-
-#--- insert.ld
-MEMORY {
- a : ORIGIN = 0, LENGTH = 1
-}
-
-SECTIONS {
- .a : { *(.two_byte_section) } >a
-}
-
-SECTIONS {
- .b : { *(.one_byte_section) } >a
-} INSERT AFTER .a;
-
-#--- overwrite-sections.ld
-MEMORY {
- a : ORIGIN = 0, LENGTH = 1
-}
-
-SECTIONS {
- .a : { *(.two_byte_section) } >a
-}
-
-OVERWRITE_SECTIONS {
- .b : { *(.one_byte_section) } >a
-}
-
-#--- link-order.s
-.section .a,"a", at progbits
-.fill 1
-
-.section .b,"a", at progbits
-.fill 1
-
-.section .c,"a", at progbits
-.fill 1
-
-.section .link_order.a,"ao", at progbits,.a
-.byte 1
-
-.section .link_order.b,"ao", at progbits,.b
-.byte 2
-
-.section .link_order.c,"ao", at progbits,.c
-.byte 3
-
-#--- link-order.ld
-MEMORY {
- order : ORIGIN = 0, LENGTH = 3
- potential_a : ORIGIN = 3, LENGTH = 0
- bc : ORIGIN = 3, LENGTH = 2
- actual_a : ORIGIN = 5, LENGTH = 1
-}
-
-SECTIONS {
- .order : { *(.link_order.*) } > order
- .potential_a : { *(.a) } >potential_a
- .bc : { *(.b) *(.c) } >bc
- .actual_a : { *(.a) } >actual_a
-}
More information about the llvm-branch-commits
mailing list