[lld] 6c81493 - [ELF] Don't use multiple inheritance for OutputSection. NFC
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 8 11:23:45 PST 2022
Author: Fangrui Song
Date: 2022-03-08T11:23:42-08:00
New Revision: 6c814931bcaa547c22b10b9ac4ac1f3285da59d3
URL: https://github.com/llvm/llvm-project/commit/6c814931bcaa547c22b10b9ac4ac1f3285da59d3
DIFF: https://github.com/llvm/llvm-project/commit/6c814931bcaa547c22b10b9ac4ac1f3285da59d3.diff
LOG: [ELF] Don't use multiple inheritance for OutputSection. NFC
Add an OutputDesc class inheriting from SectionCommand. An OutputDesc wraps an
OutputSection. This change allows InputSection::getParent to be inlined.
Differential Revision: https://reviews.llvm.org/D120650
Added:
Modified:
lld/ELF/Driver.cpp
lld/ELF/ICF.cpp
lld/ELF/LinkerScript.cpp
lld/ELF/LinkerScript.h
lld/ELF/MapFile.cpp
lld/ELF/OutputSections.cpp
lld/ELF/OutputSections.h
lld/ELF/ScriptParser.cpp
lld/ELF/SyntheticSections.cpp
lld/ELF/Writer.cpp
Removed:
################################################################################
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index ed9566f7fedee..2a1fe198a9275 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -2690,8 +2690,8 @@ void LinkerDriver::link(opt::InputArgList &args) {
// point onwards InputSectionDescription::sections should be used instead of
// sectionBases.
for (SectionCommand *cmd : script->sectionCommands)
- if (auto *sec = dyn_cast<OutputSection>(cmd))
- sec->finalizeInputSections();
+ if (auto *osd = dyn_cast<OutputDesc>(cmd))
+ osd->osec.finalizeInputSections();
llvm::erase_if(inputSections, [](InputSectionBase *s) {
return isa<MergeInputSection>(s);
});
diff --git a/lld/ELF/ICF.cpp b/lld/ELF/ICF.cpp
index a72d172b71db6..f4e4389b41fc4 100644
--- a/lld/ELF/ICF.cpp
+++ b/lld/ELF/ICF.cpp
@@ -568,8 +568,8 @@ template <class ELFT> void ICF<ELFT>::run() {
// InputSectionDescription::sections is populated by processSectionCommands().
// ICF may fold some input sections assigned to output sections. Remove them.
for (SectionCommand *cmd : script->sectionCommands)
- if (auto *sec = dyn_cast<OutputSection>(cmd))
- for (SectionCommand *subCmd : sec->commands)
+ if (auto *osd = dyn_cast<OutputDesc>(cmd))
+ for (SectionCommand *subCmd : osd->osec.commands)
if (auto *isd = dyn_cast<InputSectionDescription>(subCmd))
llvm::erase_if(isd->sections,
[](InputSection *isec) { return !isec->isLive(); });
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 88eb2b263224c..911d6dfbe113d 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -130,26 +130,26 @@ uint64_t ExprValue::getSectionOffset() const {
return getValue() - getSecAddr();
}
-OutputSection *LinkerScript::createOutputSection(StringRef name,
- StringRef location) {
- OutputSection *&secRef = nameToOutputSection[CachedHashStringRef(name)];
- OutputSection *sec;
- if (secRef && secRef->location.empty()) {
+OutputDesc *LinkerScript::createOutputSection(StringRef name,
+ StringRef location) {
+ OutputDesc *&secRef = nameToOutputSection[CachedHashStringRef(name)];
+ OutputDesc *sec;
+ if (secRef && secRef->osec.location.empty()) {
// There was a forward reference.
sec = secRef;
} else {
- sec = make<OutputSection>(name, SHT_PROGBITS, 0);
+ sec = make<OutputDesc>(name, SHT_PROGBITS, 0);
if (!secRef)
secRef = sec;
}
- sec->location = std::string(location);
+ sec->osec.location = std::string(location);
return sec;
}
-OutputSection *LinkerScript::getOrCreateOutputSection(StringRef name) {
- OutputSection *&cmdRef = nameToOutputSection[CachedHashStringRef(name)];
+OutputDesc *LinkerScript::getOrCreateOutputSection(StringRef name) {
+ OutputDesc *&cmdRef = nameToOutputSection[CachedHashStringRef(name)];
if (!cmdRef)
- cmdRef = make<OutputSection>(name, SHT_PROGBITS, 0);
+ cmdRef = make<OutputDesc>(name, SHT_PROGBITS, 0);
return cmdRef;
}
@@ -279,7 +279,7 @@ getSymbolAssignmentValues(ArrayRef<SectionCommand *> sectionCommands) {
assign->sym->value));
continue;
}
- for (SectionCommand *subCmd : cast<OutputSection>(cmd)->commands)
+ for (SectionCommand *subCmd : cast<OutputDesc>(cmd)->osec.commands)
if (auto *assign = dyn_cast<SymbolAssignment>(subCmd))
if (assign->sym)
ret.try_emplace(assign->sym, std::make_pair(assign->sym->section,
@@ -305,25 +305,25 @@ getChangedSymbolAssignment(const SymbolAssignmentMap &oldValues) {
// Process INSERT [AFTER|BEFORE] commands. For each command, we move the
// specified output section to the designated place.
void LinkerScript::processInsertCommands() {
- SmallVector<OutputSection *, 0> moves;
+ SmallVector<OutputDesc *, 0> moves;
for (const InsertCommand &cmd : insertCommands) {
for (StringRef name : cmd.names) {
// If base is empty, it may have been discarded by
// adjustOutputSections(). We do not handle such output sections.
auto from = llvm::find_if(sectionCommands, [&](SectionCommand *subCmd) {
- return isa<OutputSection>(subCmd) &&
- cast<OutputSection>(subCmd)->name == name;
+ return isa<OutputDesc>(subCmd) &&
+ cast<OutputDesc>(subCmd)->osec.name == name;
});
if (from == sectionCommands.end())
continue;
- moves.push_back(cast<OutputSection>(*from));
+ moves.push_back(cast<OutputDesc>(*from));
sectionCommands.erase(from);
}
auto insertPos =
llvm::find_if(sectionCommands, [&cmd](SectionCommand *subCmd) {
- auto *to = dyn_cast<OutputSection>(subCmd);
- return to != nullptr && to->name == cmd.where;
+ auto *to = dyn_cast<OutputDesc>(subCmd);
+ return to != nullptr && to->osec.name == cmd.where;
});
if (insertPos == sectionCommands.end()) {
error("unable to insert " + cmd.names[0] +
@@ -352,10 +352,10 @@ void LinkerScript::declareSymbols() {
// we can't say for sure if it is going to be included or not.
// Skip such sections for now. Improve the checks if we ever
// need symbols from that sections to be declared early.
- auto *sec = cast<OutputSection>(cmd);
- if (sec->constraint != ConstraintKind::NoConstraint)
+ const OutputSection &sec = cast<OutputDesc>(cmd)->osec;
+ if (sec.constraint != ConstraintKind::NoConstraint)
continue;
- for (SectionCommand *cmd : sec->commands)
+ for (SectionCommand *cmd : sec.commands)
if (auto *assign = dyn_cast<SymbolAssignment>(cmd))
declareSymbol(assign);
}
@@ -645,18 +645,20 @@ void LinkerScript::processSectionCommands() {
// Process OVERWRITE_SECTIONS first so that it can overwrite the main script
// or orphans.
- DenseMap<CachedHashStringRef, OutputSection *> map;
+ DenseMap<CachedHashStringRef, OutputDesc *> map;
size_t i = 0;
- for (OutputSection *osec : overwriteSections)
+ for (OutputDesc *osd : overwriteSections) {
+ OutputSection *osec = &osd->osec;
if (process(osec) &&
- !map.try_emplace(CachedHashStringRef(osec->name), osec).second)
+ !map.try_emplace(CachedHashStringRef(osec->name), osd).second)
warn("OVERWRITE_SECTIONS specifies duplicate " + osec->name);
+ }
for (SectionCommand *&base : sectionCommands)
- if (auto *osec = dyn_cast<OutputSection>(base)) {
- if (OutputSection *overwrite =
- map.lookup(CachedHashStringRef(osec->name))) {
- log(overwrite->location + " overwrites " + osec->name);
- overwrite->sectionIndex = i++;
+ if (auto *osd = dyn_cast<OutputDesc>(base)) {
+ OutputSection *osec = &osd->osec;
+ if (OutputDesc *overwrite = map.lookup(CachedHashStringRef(osec->name))) {
+ log(overwrite->osec.location + " overwrites " + osec->name);
+ overwrite->osec.sectionIndex = i++;
base = overwrite;
} else if (process(osec)) {
osec->sectionIndex = i++;
@@ -666,9 +668,9 @@ void LinkerScript::processSectionCommands() {
// If an OVERWRITE_SECTIONS specified output section is not in
// sectionCommands, append it to the end. The section will be inserted by
// orphan placement.
- for (OutputSection *osec : overwriteSections)
- if (osec->partition == 1 && osec->sectionIndex == UINT32_MAX)
- sectionCommands.push_back(osec);
+ for (OutputDesc *osd : overwriteSections)
+ if (osd->osec.partition == 1 && osd->osec.sectionIndex == UINT32_MAX)
+ sectionCommands.push_back(osd);
}
void LinkerScript::processSymbolAssignments() {
@@ -690,7 +692,7 @@ void LinkerScript::processSymbolAssignments() {
if (auto *assign = dyn_cast<SymbolAssignment>(cmd))
addSymbol(assign);
else
- for (SectionCommand *subCmd : cast<OutputSection>(cmd)->commands)
+ for (SectionCommand *subCmd : cast<OutputDesc>(cmd)->osec.commands)
if (auto *assign = dyn_cast<SymbolAssignment>(subCmd))
addSymbol(assign);
}
@@ -701,22 +703,20 @@ void LinkerScript::processSymbolAssignments() {
static OutputSection *findByName(ArrayRef<SectionCommand *> vec,
StringRef name) {
for (SectionCommand *cmd : vec)
- if (auto *sec = dyn_cast<OutputSection>(cmd))
- if (sec->name == name)
- return sec;
+ if (auto *osd = dyn_cast<OutputDesc>(cmd))
+ if (osd->osec.name == name)
+ return &osd->osec;
return nullptr;
}
-static OutputSection *createSection(InputSectionBase *isec,
- StringRef outsecName) {
- OutputSection *sec = script->createOutputSection(outsecName, "<internal>");
- sec->recordSection(isec);
- return sec;
+static OutputDesc *createSection(InputSectionBase *isec, StringRef outsecName) {
+ OutputDesc *osd = script->createOutputSection(outsecName, "<internal>");
+ osd->osec.recordSection(isec);
+ return osd;
}
-static OutputSection *
-addInputSec(StringMap<TinyPtrVector<OutputSection *>> &map,
- InputSectionBase *isec, StringRef outsecName) {
+static OutputDesc *addInputSec(StringMap<TinyPtrVector<OutputSection *>> &map,
+ InputSectionBase *isec, StringRef outsecName) {
// Sections with SHT_GROUP or SHF_GROUP attributes reach here only when the -r
// option is given. A section with SHT_GROUP defines a "section group", and
// its members have SHF_GROUP attribute. Usually these flags have already been
@@ -743,8 +743,9 @@ addInputSec(StringMap<TinyPtrVector<OutputSection *>> &map,
return nullptr;
}
- out->relocationSection = createSection(isec, outsecName);
- return out->relocationSection;
+ OutputDesc *osd = createSection(isec, outsecName);
+ out->relocationSection = &osd->osec;
+ return osd;
}
// The ELF spec just says
@@ -813,15 +814,15 @@ addInputSec(StringMap<TinyPtrVector<OutputSection *>> &map,
return nullptr;
}
- OutputSection *sec = createSection(isec, outsecName);
- v.push_back(sec);
- return sec;
+ OutputDesc *osd = createSection(isec, outsecName);
+ v.push_back(&osd->osec);
+ return osd;
}
// Add sections that didn't match any sections command.
void LinkerScript::addOrphanSections() {
StringMap<TinyPtrVector<OutputSection *>> map;
- SmallVector<OutputSection *, 0> v;
+ SmallVector<OutputDesc *, 0> v;
auto add = [&](InputSectionBase *s) {
if (s->isLive() && !s->parent) {
@@ -833,8 +834,8 @@ void LinkerScript::addOrphanSections() {
} else if (OutputSection *sec = findByName(sectionCommands, name)) {
sec->recordSection(s);
} else {
- if (OutputSection *os = addInputSec(map, s, name))
- v.push_back(os);
+ if (OutputDesc *osd = addInputSec(map, s, name))
+ v.push_back(osd);
assert(isa<MergeInputSection>(s) ||
s->getOutputSection()->sectionIndex == UINT32_MAX);
}
@@ -1138,9 +1139,9 @@ void LinkerScript::adjustOutputSections() {
SmallVector<StringRef, 0> defPhdrs;
for (SectionCommand *&cmd : sectionCommands) {
- auto *sec = dyn_cast<OutputSection>(cmd);
- if (!sec)
+ if (!isa<OutputDesc>(cmd))
continue;
+ auto *sec = &cast<OutputDesc>(cmd)->osec;
// Handle align (e.g. ".foo : ALIGN(16) { ... }").
if (sec->alignExpr)
@@ -1192,7 +1193,8 @@ void LinkerScript::adjustSectionsAfterSorting() {
// Try and find an appropriate memory region to assign offsets in.
MemoryRegion *hint = nullptr;
for (SectionCommand *cmd : sectionCommands) {
- if (auto *sec = dyn_cast<OutputSection>(cmd)) {
+ if (auto *osd = dyn_cast<OutputDesc>(cmd)) {
+ OutputSection *sec = &osd->osec;
if (!sec->lmaRegionName.empty()) {
if (MemoryRegion *m = memoryRegions.lookup(sec->lmaRegionName))
sec->lmaRegion = m;
@@ -1219,8 +1221,8 @@ void LinkerScript::adjustSectionsAfterSorting() {
// Walk the commands and propagate the program headers to commands that don't
// explicitly specify them.
for (SectionCommand *cmd : sectionCommands)
- if (auto *sec = dyn_cast<OutputSection>(cmd))
- maybePropagatePhdrs(*sec, defPhdrs);
+ if (auto *osd = dyn_cast<OutputDesc>(cmd))
+ maybePropagatePhdrs(osd->osec, defPhdrs);
}
static uint64_t computeBase(uint64_t min, bool allocateHeaders) {
@@ -1315,7 +1317,7 @@ const Defined *LinkerScript::assignAddresses() {
assign->size = dot - assign->addr;
continue;
}
- assignOffsets(cast<OutputSection>(cmd));
+ assignOffsets(&cast<OutputDesc>(cmd)->osec);
}
ctx = nullptr;
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index 7b45c469583b2..315b64371b28a 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -32,6 +32,7 @@ class InputSectionBase;
class OutputSection;
class SectionBase;
class ThunkSection;
+struct OutputDesc;
// This represents an r-value in the linker script.
struct ExprValue {
@@ -267,8 +268,7 @@ class LinkerScript final {
uint64_t tbssAddr = 0;
};
- llvm::DenseMap<llvm::CachedHashStringRef, OutputSection *>
- nameToOutputSection;
+ llvm::DenseMap<llvm::CachedHashStringRef, OutputDesc *> nameToOutputSection;
void addSymbol(SymbolAssignment *cmd);
void assignSymbol(SymbolAssignment *cmd, bool inSec);
@@ -304,8 +304,8 @@ class LinkerScript final {
uint64_t dot;
public:
- OutputSection *createOutputSection(StringRef name, StringRef location);
- OutputSection *getOrCreateOutputSection(StringRef name);
+ OutputDesc *createOutputSection(StringRef name, StringRef location);
+ OutputDesc *getOrCreateOutputSection(StringRef name);
bool hasPhdrsCommands() { return !phdrsCommands.empty(); }
uint64_t getDot() { return dot; }
@@ -357,7 +357,7 @@ class LinkerScript final {
SmallVector<InsertCommand, 0> insertCommands;
// OutputSections specified by OVERWRITE_SECTIONS.
- SmallVector<OutputSection *, 0> overwriteSections;
+ SmallVector<OutputDesc *, 0> overwriteSections;
// Sections that will be warned/errored by --orphan-handling.
SmallVector<const InputSectionBase *, 0> orphanSections;
diff --git a/lld/ELF/MapFile.cpp b/lld/ELF/MapFile.cpp
index 461c3a0b7d60f..048d41b8d0eeb 100644
--- a/lld/ELF/MapFile.cpp
+++ b/lld/ELF/MapFile.cpp
@@ -168,7 +168,7 @@ static void writeMapFile(raw_fd_ostream &os) {
continue;
}
- osec = cast<OutputSection>(cmd);
+ osec = &cast<OutputDesc>(cmd)->osec;
writeHeader(os, osec->addr, osec->getLMA(), osec->size, osec->alignment);
os << osec->name << '\n';
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index 1e901b89272a5..ee9162ac6b41c 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -68,8 +68,7 @@ void OutputSection::writeHeaderTo(typename ELFT::Shdr *shdr) {
}
OutputSection::OutputSection(StringRef name, uint32_t type, uint64_t flags)
- : SectionCommand(OutputSectionKind),
- SectionBase(Output, name, flags, /*Entsize*/ 0, /*Alignment*/ 1, type,
+ : SectionBase(Output, name, flags, /*Entsize*/ 0, /*Alignment*/ 1, type,
/*Info*/ 0, /*Link*/ 0) {}
// We allow sections of types listed below to merged into a
@@ -251,10 +250,6 @@ uint64_t elf::getHeaderSize() {
return Out::elfHeader->size + Out::programHeaders->size;
}
-bool OutputSection::classof(const SectionCommand *c) {
- return c->kind == OutputSectionKind;
-}
-
void OutputSection::sort(llvm::function_ref<int(InputSectionBase *s)> order) {
assert(isLive());
for (SectionCommand *b : commands)
diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h
index 005537151e530..9179d14aef07a 100644
--- a/lld/ELF/OutputSections.h
+++ b/lld/ELF/OutputSections.h
@@ -31,7 +31,7 @@ struct CompressedData {
// It is composed of multiple InputSections.
// The writer creates multiple OutputSections and assign them unique,
// non-overlapping file offsets and VAs.
-class OutputSection final : public SectionCommand, public SectionBase {
+class OutputSection final : public SectionBase {
public:
OutputSection(StringRef name, uint32_t type, uint64_t flags);
@@ -39,8 +39,6 @@ class OutputSection final : public SectionCommand, public SectionBase {
return s->kind() == SectionBase::Output;
}
- static bool classof(const SectionCommand *c);
-
uint64_t getLMA() const { return ptLoad ? addr + ptLoad->lmaOffset : addr; }
template <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *sHdr);
@@ -119,6 +117,16 @@ class OutputSection final : public SectionCommand, public SectionBase {
std::array<uint8_t, 4> getFiller();
};
+struct OutputDesc final : SectionCommand {
+ OutputSection osec;
+ OutputDesc(StringRef name, uint32_t type, uint64_t flags)
+ : SectionCommand(OutputSectionKind), osec(name, type, flags) {}
+
+ static bool classof(const SectionCommand *c) {
+ return c->kind == OutputSectionKind;
+ }
+};
+
int getPriority(StringRef s);
InputSection *getFirstInputSection(const OutputSection *os);
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 04d967999bce7..c58309b12e576 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -91,8 +91,8 @@ class ScriptParser final : ScriptLexer {
std::array<uint8_t, 4> readFill();
bool readSectionDirective(OutputSection *cmd, StringRef tok1, StringRef tok2);
void readSectionAddressType(OutputSection *cmd);
- OutputSection *readOverlaySectionDescription();
- OutputSection *readOutputSectionDescription(StringRef outSec);
+ OutputDesc *readOverlaySectionDescription();
+ OutputDesc *readOutputSectionDescription(StringRef outSec);
SmallVector<SectionCommand *, 0> readOverlay();
SmallVector<StringRef, 0> readOutputSectionPhdrs();
std::pair<uint64_t, uint64_t> readInputSectionFlags();
@@ -534,14 +534,14 @@ SmallVector<SectionCommand *, 0> ScriptParser::readOverlay() {
while (!errorCount() && !consume("}")) {
// VA is the same for all sections. The LMAs are consecutive in memory
// starting from the base load address specified.
- OutputSection *os = readOverlaySectionDescription();
- os->addrExpr = addrExpr;
+ OutputDesc *osd = readOverlaySectionDescription();
+ osd->osec.addrExpr = addrExpr;
if (prev)
- os->lmaExpr = [=] { return prev->getLMA() + prev->size; };
+ osd->osec.lmaExpr = [=] { return prev->getLMA() + prev->size; };
else
- os->lmaExpr = lmaExpr;
- v.push_back(os);
- prev = os;
+ osd->osec.lmaExpr = lmaExpr;
+ v.push_back(osd);
+ prev = &osd->osec;
}
// According to the specification, at the end of the overlay, the location
@@ -551,7 +551,7 @@ SmallVector<SectionCommand *, 0> ScriptParser::readOverlay() {
Expr moveDot = [=] {
uint64_t max = 0;
for (SectionCommand *cmd : v)
- max = std::max(max, cast<OutputSection>(cmd)->size);
+ max = std::max(max, cast<OutputDesc>(cmd)->osec.size);
return addrExpr().getValue() + max;
};
v.push_back(make<SymbolAssignment>(".", moveDot, getCurrentLocation()));
@@ -599,8 +599,8 @@ void ScriptParser::readSections() {
StringRef where = next();
SmallVector<StringRef, 0> names;
for (SectionCommand *cmd : v)
- if (auto *os = dyn_cast<OutputSection>(cmd))
- names.push_back(os->name);
+ if (auto *os = dyn_cast<OutputDesc>(cmd))
+ names.push_back(os->osec.name);
if (!names.empty())
script->insertCommands.push_back({std::move(names), isAfter, where});
}
@@ -869,45 +869,44 @@ static Expr checkAlignment(Expr e, std::string &loc) {
};
}
-OutputSection *ScriptParser::readOverlaySectionDescription() {
- OutputSection *cmd =
- script->createOutputSection(next(), getCurrentLocation());
- cmd->inOverlay = true;
+OutputDesc *ScriptParser::readOverlaySectionDescription() {
+ OutputDesc *osd = script->createOutputSection(next(), getCurrentLocation());
+ osd->osec.inOverlay = true;
expect("{");
while (!errorCount() && !consume("}")) {
uint64_t withFlags = 0;
uint64_t withoutFlags = 0;
if (consume("INPUT_SECTION_FLAGS"))
std::tie(withFlags, withoutFlags) = readInputSectionFlags();
- cmd->commands.push_back(
+ osd->osec.commands.push_back(
readInputSectionRules(next(), withFlags, withoutFlags));
}
- return cmd;
+ return osd;
}
-OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) {
- OutputSection *cmd =
- script->createOutputSection(outSec, getCurrentLocation());
+OutputDesc *ScriptParser::readOutputSectionDescription(StringRef outSec) {
+ OutputDesc *cmd = script->createOutputSection(outSec, getCurrentLocation());
+ OutputSection *osec = &cmd->osec;
size_t symbolsReferenced = script->referencedSymbols.size();
if (peek() != ":")
- readSectionAddressType(cmd);
+ readSectionAddressType(osec);
expect(":");
std::string location = getCurrentLocation();
if (consume("AT"))
- cmd->lmaExpr = readParenExpr();
+ osec->lmaExpr = readParenExpr();
if (consume("ALIGN"))
- cmd->alignExpr = checkAlignment(readParenExpr(), location);
+ osec->alignExpr = checkAlignment(readParenExpr(), location);
if (consume("SUBALIGN"))
- cmd->subalignExpr = checkAlignment(readParenExpr(), location);
+ osec->subalignExpr = checkAlignment(readParenExpr(), location);
// Parse constraints.
if (consume("ONLY_IF_RO"))
- cmd->constraint = ConstraintKind::ReadOnly;
+ osec->constraint = ConstraintKind::ReadOnly;
if (consume("ONLY_IF_RW"))
- cmd->constraint = ConstraintKind::ReadWrite;
+ osec->constraint = ConstraintKind::ReadWrite;
expect("{");
while (!errorCount() && !consume("}")) {
@@ -915,9 +914,9 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) {
if (tok == ";") {
// Empty commands are allowed. Do nothing here.
} else if (SymbolAssignment *assign = readAssignment(tok)) {
- cmd->commands.push_back(assign);
+ osec->commands.push_back(assign);
} else if (ByteCommand *data = readByteCommand(tok)) {
- cmd->commands.push_back(data);
+ osec->commands.push_back(data);
} else if (tok == "CONSTRUCTORS") {
// CONSTRUCTORS is a keyword to make the linker recognize C++ ctors/dtors
// by name. This is for very old file formats such as ECOFF/XCOFF.
@@ -928,13 +927,13 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) {
// https://sourceware.org/binutils/docs/ld/Output-Section-Data.html
if (peek() != "(")
setError("( expected, but got " + peek());
- cmd->filler = readFill();
+ osec->filler = readFill();
} else if (tok == "SORT") {
readSort();
} else if (tok == "INCLUDE") {
readInclude();
} else if (peek() == "(") {
- cmd->commands.push_back(readInputSectionDescription(tok));
+ osec->commands.push_back(readInputSectionDescription(tok));
} else {
// We have a file name and no input sections description. It is not a
// commonly used syntax, but still acceptable. In that case, all sections
@@ -944,27 +943,27 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) {
// case above.
auto *isd = make<InputSectionDescription>(tok);
isd->sectionPatterns.push_back({{}, StringMatcher("*")});
- cmd->commands.push_back(isd);
+ osec->commands.push_back(isd);
}
}
if (consume(">"))
- cmd->memoryRegionName = std::string(next());
+ osec->memoryRegionName = std::string(next());
if (consume("AT")) {
expect(">");
- cmd->lmaRegionName = std::string(next());
+ osec->lmaRegionName = std::string(next());
}
- if (cmd->lmaExpr && !cmd->lmaRegionName.empty())
+ if (osec->lmaExpr && !osec->lmaRegionName.empty())
error("section can't have both LMA and a load region");
- cmd->phdrs = readOutputSectionPhdrs();
+ osec->phdrs = readOutputSectionPhdrs();
if (peek() == "=" || peek().startswith("=")) {
inExpr = true;
consume("=");
- cmd->filler = readFill();
+ osec->filler = readFill();
inExpr = false;
}
@@ -972,7 +971,7 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) {
consume(",");
if (script->referencedSymbols.size() > symbolsReferenced)
- cmd->expressionsUseSymbols = true;
+ osec->expressionsUseSymbols = true;
return cmd;
}
@@ -1318,7 +1317,7 @@ Expr ScriptParser::readPrimary() {
}
if (tok == "ADDR") {
StringRef name = readParenLiteral();
- OutputSection *osec = script->getOrCreateOutputSection(name);
+ OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
osec->usedInExpression = true;
return [=]() -> ExprValue {
checkIfExists(*osec, location);
@@ -1343,7 +1342,7 @@ Expr ScriptParser::readPrimary() {
}
if (tok == "ALIGNOF") {
StringRef name = readParenLiteral();
- OutputSection *osec = script->getOrCreateOutputSection(name);
+ OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
return [=] {
checkIfExists(*osec, location);
return osec->alignment;
@@ -1398,7 +1397,7 @@ Expr ScriptParser::readPrimary() {
}
if (tok == "LOADADDR") {
StringRef name = readParenLiteral();
- OutputSection *osec = script->getOrCreateOutputSection(name);
+ OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
osec->usedInExpression = true;
return [=] {
checkIfExists(*osec, location);
@@ -1442,7 +1441,7 @@ Expr ScriptParser::readPrimary() {
}
if (tok == "SIZEOF") {
StringRef name = readParenLiteral();
- OutputSection *cmd = script->getOrCreateOutputSection(name);
+ OutputSection *cmd = &script->getOrCreateOutputSection(name)->osec;
// Linker script does not create an output section if its content is empty.
// We want to allow SIZEOF(.foo) where .foo is a section which happened to
// be empty.
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index c681f2ea0ff5c..41c890b0ec0a1 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -2319,7 +2319,7 @@ bool SymtabShndxSection::isNeeded() const {
// a .symtab_shndx section when the amount of output sections is huge.
size_t size = 0;
for (SectionCommand *cmd : script->sectionCommands)
- if (isa<OutputSection>(cmd))
+ if (isa<OutputDesc>(cmd))
++size;
return size >= SHN_LORESERVE;
}
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 08e51c3366776..7c596bb788f58 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -273,9 +273,9 @@ void elf::addReservedSymbols() {
static OutputSection *findSection(StringRef name, unsigned partition = 1) {
for (SectionCommand *cmd : script->sectionCommands)
- if (auto *sec = dyn_cast<OutputSection>(cmd))
- if (sec->name == name && sec->partition == partition)
- return sec;
+ if (auto *osd = dyn_cast<OutputDesc>(cmd))
+ if (osd->osec.name == name && osd->osec.partition == partition)
+ return &osd->osec;
return nullptr;
}
@@ -708,9 +708,10 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
// don't create a section symbol for that section.
template <class ELFT> void Writer<ELFT>::addSectionSymbols() {
for (SectionCommand *cmd : script->sectionCommands) {
- auto *sec = dyn_cast<OutputSection>(cmd);
- if (!sec)
+ auto *osd = dyn_cast<OutputDesc>(cmd);
+ if (!osd)
continue;
+ OutputSection *sec = &osd->osec;
auto i = llvm::find_if(sec->commands, [](SectionCommand *cmd) {
if (auto *isd = dyn_cast<InputSectionDescription>(cmd))
return !isd->sections.empty();
@@ -974,8 +975,8 @@ static unsigned getSectionRank(const OutputSection &osec) {
static bool compareSections(const SectionCommand *aCmd,
const SectionCommand *bCmd) {
- const OutputSection *a = cast<OutputSection>(aCmd);
- const OutputSection *b = cast<OutputSection>(bCmd);
+ const OutputSection *a = &cast<OutputDesc>(aCmd)->osec;
+ const OutputSection *b = &cast<OutputDesc>(bCmd)->osec;
if (a->sortRank != b->sortRank)
return a->sortRank < b->sortRank;
@@ -1106,13 +1107,15 @@ template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() {
// The more branches in getSectionRank that match, the more similar they are.
// Since each branch corresponds to a bit flag, we can just use
// countLeadingZeros.
-static int getRankProximityAux(OutputSection *a, OutputSection *b) {
- return countLeadingZeros(a->sortRank ^ b->sortRank);
+static int getRankProximityAux(const OutputSection &a, const OutputSection &b) {
+ return countLeadingZeros(a.sortRank ^ b.sortRank);
}
static int getRankProximity(OutputSection *a, SectionCommand *b) {
- auto *sec = dyn_cast<OutputSection>(b);
- return (sec && sec->hasInputSections) ? getRankProximityAux(a, sec) : -1;
+ auto *osd = dyn_cast<OutputDesc>(b);
+ return (osd && osd->osec.hasInputSections)
+ ? getRankProximityAux(*a, osd->osec)
+ : -1;
}
// When placing orphan sections, we want to place them after symbol assignments
@@ -1141,7 +1144,7 @@ static bool shouldSkip(SectionCommand *cmd) {
static SmallVectorImpl<SectionCommand *>::iterator
findOrphanPos(SmallVectorImpl<SectionCommand *>::iterator b,
SmallVectorImpl<SectionCommand *>::iterator e) {
- OutputSection *sec = cast<OutputSection>(*e);
+ OutputSection *sec = &cast<OutputDesc>(*e)->osec;
// Find the first element that has as close a rank as possible.
auto i = std::max_element(b, e, [=](SectionCommand *a, SectionCommand *b) {
@@ -1149,9 +1152,9 @@ findOrphanPos(SmallVectorImpl<SectionCommand *>::iterator b,
});
if (i == e)
return e;
- auto foundSec = dyn_cast<OutputSection>(*i);
- if (!foundSec)
+ if (!isa<OutputDesc>(*i))
return e;
+ auto foundSec = &cast<OutputDesc>(*i)->osec;
// Consider all existing sections with the same proximity.
int proximity = getRankProximity(sec, *i);
@@ -1165,17 +1168,17 @@ findOrphanPos(SmallVectorImpl<SectionCommand *>::iterator b,
// resemble the behavior of GNU ld.
sortRank = std::max(sortRank, foundSec->sortRank);
for (; i != e; ++i) {
- auto *curSec = dyn_cast<OutputSection>(*i);
- if (!curSec || !curSec->hasInputSections)
+ auto *curSecDesc = dyn_cast<OutputDesc>(*i);
+ if (!curSecDesc || !curSecDesc->osec.hasInputSections)
continue;
- if (getRankProximity(sec, curSec) != proximity ||
- sortRank < curSec->sortRank)
+ if (getRankProximity(sec, curSecDesc) != proximity ||
+ sortRank < curSecDesc->osec.sortRank)
break;
}
auto isOutputSecWithInputSections = [](SectionCommand *cmd) {
- auto *os = dyn_cast<OutputSection>(cmd);
- return os && os->hasInputSections;
+ auto *osd = dyn_cast<OutputDesc>(cmd);
+ return osd && osd->osec.hasInputSections;
};
auto j =
std::find_if(std::make_reverse_iterator(i), std::make_reverse_iterator(b),
@@ -1412,8 +1415,8 @@ template <class ELFT> void Writer<ELFT>::sortInputSections() {
DenseMap<const InputSectionBase *, int> order = buildSectionOrder();
maybeShuffle(order);
for (SectionCommand *cmd : script->sectionCommands)
- if (auto *sec = dyn_cast<OutputSection>(cmd))
- sortSection(*sec, order);
+ if (auto *osd = dyn_cast<OutputDesc>(cmd))
+ sortSection(osd->osec, order);
}
template <class ELFT> void Writer<ELFT>::sortSections() {
@@ -1429,13 +1432,11 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
sortInputSections();
for (SectionCommand *cmd : script->sectionCommands)
- if (auto *osec = dyn_cast<OutputSection>(cmd))
- osec->sortRank = getSectionRank(*osec);
+ if (auto *osd = dyn_cast<OutputDesc>(cmd))
+ osd->osec.sortRank = getSectionRank(osd->osec);
if (!script->hasSectionsCommand) {
// We know that all the OutputSections are contiguous in this case.
- auto isSection = [](SectionCommand *cmd) {
- return isa<OutputSection>(cmd);
- };
+ auto isSection = [](SectionCommand *cmd) { return isa<OutputDesc>(cmd); };
std::stable_sort(
llvm::find_if(script->sectionCommands, isSection),
llvm::find_if(llvm::reverse(script->sectionCommands), isSection).base(),
@@ -1492,8 +1493,8 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
auto i = script->sectionCommands.begin();
auto e = script->sectionCommands.end();
auto nonScriptI = std::find_if(i, e, [](SectionCommand *cmd) {
- if (auto *sec = dyn_cast<OutputSection>(cmd))
- return sec->sectionIndex == UINT32_MAX;
+ if (auto *osd = dyn_cast<OutputDesc>(cmd))
+ return osd->osec.sectionIndex == UINT32_MAX;
return false;
});
@@ -1513,13 +1514,13 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
while (nonScriptI != e) {
auto pos = findOrphanPos(i, nonScriptI);
- OutputSection *orphan = cast<OutputSection>(*nonScriptI);
+ OutputSection *orphan = &cast<OutputDesc>(*nonScriptI)->osec;
// As an optimization, find all sections with the same sort rank
// and insert them with one rotate.
unsigned rank = orphan->sortRank;
auto end = std::find_if(nonScriptI + 1, e, [=](SectionCommand *cmd) {
- return cast<OutputSection>(cmd)->sortRank != rank;
+ return cast<OutputDesc>(cmd)->osec.sortRank != rank;
});
std::rotate(pos, nonScriptI, end);
nonScriptI = end;
@@ -1668,11 +1669,13 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
// If addrExpr is set, the address may not be a multiple of the alignment.
// Warn because this is error-prone.
for (SectionCommand *cmd : script->sectionCommands)
- if (auto *os = dyn_cast<OutputSection>(cmd))
- if (os->addr % os->alignment != 0)
- warn("address (0x" + Twine::utohexstr(os->addr) + ") of section " +
- os->name + " is not a multiple of alignment (" +
- Twine(os->alignment) + ")");
+ if (auto *osd = dyn_cast<OutputDesc>(cmd)) {
+ OutputSection *osec = &osd->osec;
+ if (osec->addr % osec->alignment != 0)
+ warn("address (0x" + Twine::utohexstr(osec->addr) + ") of section " +
+ osec->name + " is not a multiple of alignment (" +
+ Twine(osec->alignment) + ")");
+ }
}
// If Input Sections have been shrunk (basic block sections) then
@@ -1819,8 +1822,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
if (!config->relocatable) {
addStartEndSymbols();
for (SectionCommand *cmd : script->sectionCommands)
- if (auto *sec = dyn_cast<OutputSection>(cmd))
- addStartStopSymbols(*sec);
+ if (auto *osd = dyn_cast<OutputDesc>(cmd))
+ addStartStopSymbols(osd->osec);
}
// Add _DYNAMIC symbol. Unlike GNU gold, our _DYNAMIC symbol has no type.
@@ -1988,7 +1991,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
// Create a list of OutputSections, assign sectionIndex, and populate
// in.shStrTab.
for (SectionCommand *cmd : script->sectionCommands)
- if (auto *osec = dyn_cast<OutputSection>(cmd)) {
+ if (auto *osd = dyn_cast<OutputDesc>(cmd)) {
+ OutputSection *osec = &osd->osec;
outputSections.push_back(osec);
osec->sectionIndex = outputSections.size();
osec->shName = in.shStrTab->addString(osec->name);
More information about the llvm-commits
mailing list