[lld] 81f34af - Revert "[LLD] Implement --enable-non-contiguous-regions" (#92005)

via llvm-commits llvm-commits at lists.llvm.org
Mon May 13 10:38:43 PDT 2024


Author: Daniel Thornburgh
Date: 2024-05-13T10:38:40-07:00
New Revision: 81f34afa5c39584c2721000e2bcf3b8ec02a4f4d

URL: https://github.com/llvm/llvm-project/commit/81f34afa5c39584c2721000e2bcf3b8ec02a4f4d
DIFF: https://github.com/llvm/llvm-project/commit/81f34afa5c39584c2721000e2bcf3b8ec02a4f4d.diff

LOG: Revert "[LLD] Implement --enable-non-contiguous-regions" (#92005)

Reverts llvm/llvm-project#90007

Broke in merging I think.

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 &sections = 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-commits mailing list