[ELF] LinkerScript/OutputSection: change other std::vector members to SmallVector

11+KiB smaller .text with both libc++ and libstdc++ builds.
This commit is contained in:
Fangrui Song 2021-12-26 13:53:47 -08:00
parent 31cfb3f4f6
commit a1c2ee0147
7 changed files with 51 additions and 52 deletions

View File

@ -306,7 +306,7 @@ getChangedSymbolAssignment(const SymbolAssignmentMap &oldValues) {
// Process INSERT [AFTER|BEFORE] commands. For each command, we move the // Process INSERT [AFTER|BEFORE] commands. For each command, we move the
// specified output section to the designated place. // specified output section to the designated place.
void LinkerScript::processInsertCommands() { void LinkerScript::processInsertCommands() {
std::vector<OutputSection *> moves; SmallVector<OutputSection *, 0> moves;
for (const InsertCommand &cmd : insertCommands) { for (const InsertCommand &cmd : insertCommands) {
for (StringRef name : cmd.names) { for (StringRef name : cmd.names) {
// If base is empty, it may have been discarded by // If base is empty, it may have been discarded by
@ -490,7 +490,7 @@ SmallVector<InputSectionBase *, 0>
LinkerScript::computeInputSections(const InputSectionDescription *cmd, LinkerScript::computeInputSections(const InputSectionDescription *cmd,
ArrayRef<InputSectionBase *> sections) { ArrayRef<InputSectionBase *> sections) {
SmallVector<InputSectionBase *, 0> ret; SmallVector<InputSectionBase *, 0> ret;
std::vector<size_t> indexes; SmallVector<size_t, 0> indexes;
DenseSet<size_t> seen; DenseSet<size_t> seen;
auto sortByPositionThenCommandLine = [&](size_t begin, size_t end) { auto sortByPositionThenCommandLine = [&](size_t begin, size_t end) {
llvm::sort(MutableArrayRef<size_t>(indexes).slice(begin, end - begin)); llvm::sort(MutableArrayRef<size_t>(indexes).slice(begin, end - begin));
@ -827,7 +827,7 @@ addInputSec(StringMap<TinyPtrVector<OutputSection *>> &map,
// Add sections that didn't match any sections command. // Add sections that didn't match any sections command.
void LinkerScript::addOrphanSections() { void LinkerScript::addOrphanSections() {
StringMap<TinyPtrVector<OutputSection *>> map; StringMap<TinyPtrVector<OutputSection *>> map;
std::vector<OutputSection *> v; SmallVector<OutputSection *, 0> v;
std::function<void(InputSectionBase *)> add; std::function<void(InputSectionBase *)> add;
add = [&](InputSectionBase *s) { add = [&](InputSectionBase *s) {
@ -1110,7 +1110,7 @@ bool LinkerScript::isDiscarded(const OutputSection *sec) const {
} }
static void maybePropagatePhdrs(OutputSection &sec, static void maybePropagatePhdrs(OutputSection &sec,
std::vector<StringRef> &phdrs) { SmallVector<StringRef, 0> &phdrs) {
if (sec.phdrs.empty()) { if (sec.phdrs.empty()) {
// To match the bfd linker script behaviour, only propagate program // To match the bfd linker script behaviour, only propagate program
// headers to sections that are allocated. // headers to sections that are allocated.
@ -1144,7 +1144,7 @@ void LinkerScript::adjustSectionsBeforeSorting() {
// the previous sections. Only a few flags are needed to keep the impact low. // the previous sections. Only a few flags are needed to keep the impact low.
uint64_t flags = SHF_ALLOC; uint64_t flags = SHF_ALLOC;
std::vector<StringRef> defPhdrs; SmallVector<StringRef, 0> defPhdrs;
for (SectionCommand *&cmd : sectionCommands) { for (SectionCommand *&cmd : sectionCommands) {
auto *sec = dyn_cast<OutputSection>(cmd); auto *sec = dyn_cast<OutputSection>(cmd);
if (!sec) if (!sec)
@ -1215,7 +1215,7 @@ void LinkerScript::adjustSectionsAfterSorting() {
// Below is an example of such linker script: // Below is an example of such linker script:
// PHDRS { seg PT_LOAD; } // PHDRS { seg PT_LOAD; }
// SECTIONS { .aaa : { *(.aaa) } } // SECTIONS { .aaa : { *(.aaa) } }
std::vector<StringRef> defPhdrs; SmallVector<StringRef, 0> defPhdrs;
auto firstPtLoad = llvm::find_if(phdrsCommands, [](const PhdrsCommand &cmd) { auto firstPtLoad = llvm::find_if(phdrsCommands, [](const PhdrsCommand &cmd) {
return cmd.type == PT_LOAD; return cmd.type == PT_LOAD;
}); });
@ -1245,7 +1245,7 @@ static uint64_t computeBase(uint64_t min, bool allocateHeaders) {
// We check if the headers fit below the first allocated section. If there isn't // We check if the headers fit below the first allocated section. If there isn't
// enough space for these sections, we'll remove them from the PT_LOAD segment, // enough space for these sections, we'll remove them from the PT_LOAD segment,
// and we'll also remove the PT_PHDR segment. // and we'll also remove the PT_PHDR segment.
void LinkerScript::allocateHeaders(std::vector<PhdrEntry *> &phdrs) { void LinkerScript::allocateHeaders(SmallVector<PhdrEntry *, 0> &phdrs) {
uint64_t min = std::numeric_limits<uint64_t>::max(); uint64_t min = std::numeric_limits<uint64_t>::max();
for (OutputSection *sec : outputSections) for (OutputSection *sec : outputSections)
if (sec->flags & SHF_ALLOC) if (sec->flags & SHF_ALLOC)
@ -1329,8 +1329,8 @@ const Defined *LinkerScript::assignAddresses() {
} }
// Creates program headers as instructed by PHDRS linker script command. // Creates program headers as instructed by PHDRS linker script command.
std::vector<PhdrEntry *> LinkerScript::createPhdrs() { SmallVector<PhdrEntry *, 0> LinkerScript::createPhdrs() {
std::vector<PhdrEntry *> ret; SmallVector<PhdrEntry *, 0> ret;
// Process PHDRS and FILEHDR keywords because they are not // Process PHDRS and FILEHDR keywords because they are not
// real output sections and cannot be added in the following loop. // real output sections and cannot be added in the following loop.
@ -1412,8 +1412,8 @@ static Optional<size_t> getPhdrIndex(ArrayRef<PhdrsCommand> vec,
// Returns indices of ELF headers containing specific section. Each index is a // Returns indices of ELF headers containing specific section. Each index is a
// zero based number of ELF header listed within PHDRS {} script block. // zero based number of ELF header listed within PHDRS {} script block.
std::vector<size_t> LinkerScript::getPhdrIndices(OutputSection *cmd) { SmallVector<size_t, 0> LinkerScript::getPhdrIndices(OutputSection *cmd) {
std::vector<size_t> ret; SmallVector<size_t, 0> ret;
for (StringRef s : cmd->phdrs) { for (StringRef s : cmd->phdrs) {
if (Optional<size_t> idx = getPhdrIndex(phdrsCommands, s)) if (Optional<size_t> idx = getPhdrIndex(phdrsCommands, s))

View File

@ -244,7 +244,7 @@ struct ByteCommand : SectionCommand {
}; };
struct InsertCommand { struct InsertCommand {
std::vector<StringRef> names; SmallVector<StringRef, 0> names;
bool isAfter; bool isAfter;
StringRef where; StringRef where;
}; };
@ -287,7 +287,7 @@ class LinkerScript final {
void discardSynthetic(OutputSection &); void discardSynthetic(OutputSection &);
std::vector<size_t> getPhdrIndices(OutputSection *sec); SmallVector<size_t, 0> getPhdrIndices(OutputSection *sec);
std::pair<MemoryRegion *, MemoryRegion *> std::pair<MemoryRegion *, MemoryRegion *>
findMemoryRegion(OutputSection *sec, MemoryRegion *hint); findMemoryRegion(OutputSection *sec, MemoryRegion *hint);
@ -321,12 +321,12 @@ public:
void adjustSectionsBeforeSorting(); void adjustSectionsBeforeSorting();
void adjustSectionsAfterSorting(); void adjustSectionsAfterSorting();
std::vector<PhdrEntry *> createPhdrs(); SmallVector<PhdrEntry *, 0> createPhdrs();
bool needsInterpSection(); bool needsInterpSection();
bool shouldKeep(InputSectionBase *s); bool shouldKeep(InputSectionBase *s);
const Defined *assignAddresses(); const Defined *assignAddresses();
void allocateHeaders(std::vector<PhdrEntry *> &phdrs); void allocateHeaders(SmallVector<PhdrEntry *, 0> &phdrs);
void processSectionCommands(); void processSectionCommands();
void processSymbolAssignments(); void processSymbolAssignments();
void declareSymbols(); void declareSymbols();
@ -337,10 +337,10 @@ public:
void processInsertCommands(); void processInsertCommands();
// SECTIONS command list. // SECTIONS command list.
std::vector<SectionCommand *> sectionCommands; SmallVector<SectionCommand *, 0> sectionCommands;
// PHDRS command list. // PHDRS command list.
std::vector<PhdrsCommand> phdrsCommands; SmallVector<PhdrsCommand, 0> phdrsCommands;
bool hasSectionsCommand = false; bool hasSectionsCommand = false;
bool errorOnMissingSection = false; bool errorOnMissingSection = false;

View File

@ -347,7 +347,7 @@ template <class ELFT> void OutputSection::writeTo(uint8_t *buf) {
} }
// Write leading padding. // Write leading padding.
std::vector<InputSection *> sections = getInputSections(this); SmallVector<InputSection *, 0> sections = getInputSections(*this);
std::array<uint8_t, 4> filler = getFiller(); std::array<uint8_t, 4> filler = getFiller();
bool nonZeroFiller = read32(filler.data()) != 0; bool nonZeroFiller = read32(filler.data()) != 0;
if (nonZeroFiller) if (nonZeroFiller)
@ -520,9 +520,9 @@ InputSection *elf::getFirstInputSection(const OutputSection *os) {
return nullptr; return nullptr;
} }
std::vector<InputSection *> elf::getInputSections(const OutputSection *os) { SmallVector<InputSection *, 0> elf::getInputSections(const OutputSection &os) {
std::vector<InputSection *> ret; SmallVector<InputSection *, 0> ret;
for (SectionCommand *cmd : os->commands) for (SectionCommand *cmd : os.commands)
if (auto *isd = dyn_cast<InputSectionDescription>(cmd)) if (auto *isd = dyn_cast<InputSectionDescription>(cmd))
ret.insert(ret.end(), isd->sections.begin(), isd->sections.end()); ret.insert(ret.end(), isd->sections.begin(), isd->sections.end());
return ret; return ret;
@ -550,7 +550,7 @@ std::array<uint8_t, 4> OutputSection::getFiller() {
void OutputSection::checkDynRelAddends(const uint8_t *bufStart) { void OutputSection::checkDynRelAddends(const uint8_t *bufStart) {
assert(config->writeAddends && config->checkDynamicRelocs); assert(config->writeAddends && config->checkDynamicRelocs);
assert(type == SHT_REL || type == SHT_RELA); assert(type == SHT_REL || type == SHT_RELA);
std::vector<InputSection *> sections = getInputSections(this); SmallVector<InputSection *, 0> sections = getInputSections(*this);
parallelForEachN(0, sections.size(), [&](size_t i) { parallelForEachN(0, sections.size(), [&](size_t i) {
// When linking with -r or --emit-relocs we might also call this function // When linking with -r or --emit-relocs we might also call this function
// for input .rel[a].<sec> sections which we simply pass through to the // for input .rel[a].<sec> sections which we simply pass through to the

View File

@ -82,8 +82,8 @@ public:
Expr alignExpr; Expr alignExpr;
Expr lmaExpr; Expr lmaExpr;
Expr subalignExpr; Expr subalignExpr;
std::vector<SectionCommand *> commands; SmallVector<SectionCommand *, 0> commands;
std::vector<StringRef> phdrs; SmallVector<StringRef, 0> phdrs;
llvm::Optional<std::array<uint8_t, 4>> filler; llvm::Optional<std::array<uint8_t, 4>> filler;
ConstraintKind constraint = ConstraintKind::NoConstraint; ConstraintKind constraint = ConstraintKind::NoConstraint;
std::string location; std::string location;
@ -112,8 +112,8 @@ public:
private: private:
// Used for implementation of --compress-debug-sections option. // Used for implementation of --compress-debug-sections option.
std::vector<uint8_t> zDebugHeader; SmallVector<uint8_t, 0> zDebugHeader;
llvm::SmallVector<char, 0> compressedData; SmallVector<char, 0> compressedData;
std::array<uint8_t, 4> getFiller(); std::array<uint8_t, 4> getFiller();
}; };
@ -121,7 +121,7 @@ private:
int getPriority(StringRef s); int getPriority(StringRef s);
InputSection *getFirstInputSection(const OutputSection *os); InputSection *getFirstInputSection(const OutputSection *os);
std::vector<InputSection *> getInputSections(const OutputSection *os); SmallVector<InputSection *, 0> getInputSections(const OutputSection &os);
// All output sections that are handled by the linker specially are // All output sections that are handled by the linker specially are
// globally accessible. Writer initializes them, so don't use them // globally accessible. Writer initializes them, so don't use them

View File

@ -94,7 +94,7 @@ private:
OutputSection *readOverlaySectionDescription(); OutputSection *readOverlaySectionDescription();
OutputSection *readOutputSectionDescription(StringRef outSec); OutputSection *readOutputSectionDescription(StringRef outSec);
std::vector<SectionCommand *> readOverlay(); std::vector<SectionCommand *> readOverlay();
std::vector<StringRef> readOutputSectionPhdrs(); SmallVector<StringRef, 0> readOutputSectionPhdrs();
std::pair<uint64_t, uint64_t> readInputSectionFlags(); std::pair<uint64_t, uint64_t> readInputSectionFlags();
InputSectionDescription *readInputSectionDescription(StringRef tok); InputSectionDescription *readInputSectionDescription(StringRef tok);
StringMatcher readFilePatterns(); StringMatcher readFilePatterns();
@ -597,7 +597,7 @@ void ScriptParser::readSections() {
else if (!consume("BEFORE")) else if (!consume("BEFORE"))
setError("expected AFTER/BEFORE, but got '" + next() + "'"); setError("expected AFTER/BEFORE, but got '" + next() + "'");
StringRef where = next(); StringRef where = next();
std::vector<StringRef> names; SmallVector<StringRef, 0> names;
for (SectionCommand *cmd : v) for (SectionCommand *cmd : v)
if (auto *os = dyn_cast<OutputSection>(cmd)) if (auto *os = dyn_cast<OutputSection>(cmd))
names.push_back(os->name); names.push_back(os->name);
@ -1452,8 +1452,8 @@ Expr ScriptParser::readParenExpr() {
return e; return e;
} }
std::vector<StringRef> ScriptParser::readOutputSectionPhdrs() { SmallVector<StringRef, 0> ScriptParser::readOutputSectionPhdrs() {
std::vector<StringRef> phdrs; SmallVector<StringRef, 0> phdrs;
while (!errorCount() && peek().startswith(":")) { while (!errorCount() && peek().startswith(":")) {
StringRef tok = next(); StringRef tok = next();
phdrs.push_back((tok.size() == 1) ? next() : tok.substr(1)); phdrs.push_back((tok.size() == 1) ? next() : tok.substr(1));

View File

@ -1205,7 +1205,7 @@ struct Partition {
SyntheticSection *elfHeader; SyntheticSection *elfHeader;
SyntheticSection *programHeaders; SyntheticSection *programHeaders;
std::vector<PhdrEntry *> phdrs; SmallVector<PhdrEntry *, 0> phdrs;
ARMExidxSyntheticSection *armExidx; ARMExidxSyntheticSection *armExidx;
BuildIdSection *buildId; BuildIdSection *buildId;

View File

@ -65,7 +65,7 @@ private:
void checkExecuteOnly(); void checkExecuteOnly();
void setReservedSymbolSections(); void setReservedSymbolSections();
std::vector<PhdrEntry *> createPhdrs(Partition &part); SmallVector<PhdrEntry *, 0> createPhdrs(Partition &part);
void addPhdrForSection(Partition &part, unsigned shType, unsigned pType, void addPhdrForSection(Partition &part, unsigned shType, unsigned pType,
unsigned pFlags); unsigned pFlags);
void assignFileOffsets(); void assignFileOffsets();
@ -100,7 +100,7 @@ template <class ELFT> void elf::writeResult() {
Writer<ELFT>().run(); Writer<ELFT>().run();
} }
static void removeEmptyPTLoad(std::vector<PhdrEntry *> &phdrs) { static void removeEmptyPTLoad(SmallVector<PhdrEntry *, 0> &phdrs) {
auto it = std::stable_partition( auto it = std::stable_partition(
phdrs.begin(), phdrs.end(), [&](const PhdrEntry *p) { phdrs.begin(), phdrs.end(), [&](const PhdrEntry *p) {
if (p->p_type != PT_LOAD) if (p->p_type != PT_LOAD)
@ -1170,9 +1170,9 @@ static bool shouldSkip(SectionCommand *cmd) {
// We want to place orphan sections so that they share as much // We want to place orphan sections so that they share as much
// characteristics with their neighbors as possible. For example, if // characteristics with their neighbors as possible. For example, if
// both are rw, or both are tls. // both are rw, or both are tls.
static std::vector<SectionCommand *>::iterator static SmallVectorImpl<SectionCommand *>::iterator
findOrphanPos(std::vector<SectionCommand *>::iterator b, findOrphanPos(SmallVectorImpl<SectionCommand *>::iterator b,
std::vector<SectionCommand *>::iterator e) { SmallVectorImpl<SectionCommand *>::iterator e) {
OutputSection *sec = cast<OutputSection>(*e); OutputSection *sec = cast<OutputSection>(*e);
// Find the first element that has as close a rank as possible. // Find the first element that has as close a rank as possible.
@ -1332,8 +1332,8 @@ static DenseMap<const InputSectionBase *, int> buildSectionOrder() {
static void static void
sortISDBySectionOrder(InputSectionDescription *isd, sortISDBySectionOrder(InputSectionDescription *isd,
const DenseMap<const InputSectionBase *, int> &order) { const DenseMap<const InputSectionBase *, int> &order) {
std::vector<InputSection *> unorderedSections; SmallVector<InputSection *, 0> unorderedSections;
std::vector<std::pair<InputSection *, int>> orderedSections; SmallVector<std::pair<InputSection *, int>, 0> orderedSections;
uint64_t unorderedSize = 0; uint64_t unorderedSize = 0;
for (InputSection *isec : isd->sections) { for (InputSection *isec : isd->sections) {
@ -1766,10 +1766,10 @@ template <class ELFT> void Writer<ELFT>::optimizeBasicBlockJumps() {
// jump to the following section as it is not required. // jump to the following section as it is not required.
// 2. If there are two consecutive jump instructions, it checks // 2. If there are two consecutive jump instructions, it checks
// if they can be flipped and one can be deleted. // if they can be flipped and one can be deleted.
for (OutputSection *os : outputSections) { for (OutputSection *osec : outputSections) {
if (!(os->flags & SHF_EXECINSTR)) if (!(osec->flags & SHF_EXECINSTR))
continue; continue;
std::vector<InputSection *> sections = getInputSections(os); SmallVector<InputSection *, 0> sections = getInputSections(*osec);
std::vector<unsigned> result(sections.size()); std::vector<unsigned> result(sections.size());
// Delete all fall through jump instructions. Also, check if two // Delete all fall through jump instructions. Also, check if two
// consecutive jump instructions can be flipped so that a fall // consecutive jump instructions can be flipped so that a fall
@ -1790,11 +1790,9 @@ template <class ELFT> void Writer<ELFT>::optimizeBasicBlockJumps() {
fixSymbolsAfterShrinking(); fixSymbolsAfterShrinking();
for (OutputSection *os : outputSections) { for (OutputSection *osec : outputSections)
std::vector<InputSection *> sections = getInputSections(os); for (InputSection *is : getInputSections(*osec))
for (InputSection *is : sections)
is->trim(); is->trim();
}
} }
// In order to allow users to manipulate linker-synthesized sections, // In order to allow users to manipulate linker-synthesized sections,
@ -2165,11 +2163,12 @@ template <class ELFT> void Writer<ELFT>::checkExecuteOnly() {
if (!config->executeOnly) if (!config->executeOnly)
return; return;
for (OutputSection *os : outputSections) for (OutputSection *osec : outputSections)
if (os->flags & SHF_EXECINSTR) if (osec->flags & SHF_EXECINSTR)
for (InputSection *isec : getInputSections(os)) for (InputSection *isec : getInputSections(*osec))
if (!(isec->flags & SHF_EXECINSTR)) if (!(isec->flags & SHF_EXECINSTR))
error("cannot place " + toString(isec) + " into " + toString(os->name) + error("cannot place " + toString(isec) + " into " +
toString(osec->name) +
": -execute-only does not support intermingling data and code"); ": -execute-only does not support intermingling data and code");
} }
@ -2259,8 +2258,8 @@ static uint64_t computeFlags(uint64_t flags) {
// Decide which program headers to create and which sections to include in each // Decide which program headers to create and which sections to include in each
// one. // one.
template <class ELFT> template <class ELFT>
std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs(Partition &part) { SmallVector<PhdrEntry *, 0> Writer<ELFT>::createPhdrs(Partition &part) {
std::vector<PhdrEntry *> ret; SmallVector<PhdrEntry *, 0> ret;
auto addHdr = [&](unsigned type, unsigned flags) -> PhdrEntry * { auto addHdr = [&](unsigned type, unsigned flags) -> PhdrEntry * {
ret.push_back(make<PhdrEntry>(type, flags)); ret.push_back(make<PhdrEntry>(type, flags));
return ret.back(); return ret.back();