[lld] [LLD][COFF] Add support for custom section layout (PR #152779)

via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 30 02:03:56 PDT 2025


================
@@ -1413,6 +1415,30 @@ void Writer::removeUnusedSections() {
   llvm::erase_if(ctx.outputSections, isUnused);
 }
 
+void Writer::layoutSections() {
+  llvm::TimeTraceScope timeScope("Layout sections");
+  if (ctx.config.sectionOrder.empty())
+    return;
+
+  std::unordered_map<const OutputSection *, size_t> originalOrder;
+  for (size_t i = 0; i < ctx.outputSections.size(); ++i)
+    originalOrder[ctx.outputSections[i]] = i;
+
+  llvm::stable_sort(
+      ctx.outputSections,
+      [this, &originalOrder](const OutputSection *a, const OutputSection *b) {
+        auto itA = ctx.config.sectionOrder.find(a->name.str());
+        auto itB = ctx.config.sectionOrder.find(b->name.str());
+
+        if (itA != ctx.config.sectionOrder.end() &&
+            itB != ctx.config.sectionOrder.end())
+          return itA->second < itB->second;
+
+        // Not found in layout file; respect the original order
+        return originalOrder[a] < originalOrder[b];
----------------
kkent030315 wrote:

> Does `stable_sort` have any guarantees that it tests all combinations? Otherwise it seems to me that this sorting function is nondeterministic, depending on in which order the sorting implementation decides to compare things?

Apparently no, `stable_sort` has no such guarantee. I think insertion sort should suffice for this case. It costs o(n^2) but we don't need to really consider perf here since there's very limited number of sections at when `layoutSections` gets called. wdyt?

```cpp
void Writer::layoutSections() {
  llvm::TimeTraceScope timeScope("Layout sections");
  if (ctx.config.sectionOrder.empty())
    return;

  std::unordered_map<const OutputSection *, size_t> originalOrder;
  for (size_t i = 0; i < ctx.outputSections.size(); ++i)
    originalOrder[ctx.outputSections[i]] = i;

  for (size_t i = 1; i < ctx.outputSections.size(); ++i) {
    OutputSection *current = ctx.outputSections[i];
    auto itCurrent = ctx.config.sectionOrder.find(current->name.str());
    bool currentInOrder = itCurrent != ctx.config.sectionOrder.end();
    
    size_t j = i;
    while (j > 0) {
      OutputSection *prev = ctx.outputSections[j - 1];
      auto itPrev = ctx.config.sectionOrder.find(prev->name.str());
      bool prevInOrder = itPrev != ctx.config.sectionOrder.end();
      
      bool shouldMoveLeft;
      
      // Put unspecified sections after all specified sections
      if (currentInOrder && prevInOrder) {
        shouldMoveLeft = itCurrent->second < itPrev->second;
      } else if (currentInOrder && !prevInOrder) {
        shouldMoveLeft = true;
      } else if (!currentInOrder && prevInOrder) {
        shouldMoveLeft = false;
      } else {
        shouldMoveLeft = originalOrder[current] < originalOrder[prev];
      }
      
      if (!shouldMoveLeft)
        break;
      
      ctx.outputSections[j] = prev;
      j--;
    }
    
    ctx.outputSections[j] = current;
  }
}
```

https://github.com/llvm/llvm-project/pull/152779


More information about the llvm-commits mailing list