Skip to content

Commit 2b78ef0

Browse files
committed
[lld-macho][nfc] Eliminate InputSection::Shared
Earlier in LLD's evolution, I tried to create the illusion that subsections were indistinguishable from "top-level" sections. Thus, even though the subsections shared many common field values, I hid those common values away in a private Shared struct (see D105305). More recently, however, @gkm added a public `Section` struct in D113241 that served as an explicit way to store values that are common to an entire set of subsections (aka InputSections). Now that we have another "common value" struct, `Shared` has been rendered redundant. All its fields can be moved into `Section` instead, and the pointer to `Shared` can be replaced with a pointer to `Section`. This `Section` pointer also has the advantage of letting us inspect other subsections easily, simplifying the implementation of {D118798}. P.S. I do think that having both `Section` and `InputSection` makes for a slightly confusing naming scheme. I considered renaming `InputSection` to `Subsection`, but that would break the symmetry with `OutputSection`. It would also make us deviate from LLD-ELF's naming scheme. This change is perf-neutral on my 3.2 GHz 16-Core Intel Xeon W machine: base diff difference (95% CI) sys_time 1.258 ± 0.031 1.248 ± 0.023 [ -1.6% .. +0.1%] user_time 3.659 ± 0.047 3.658 ± 0.041 [ -0.5% .. +0.4%] wall_time 4.640 ± 0.085 4.625 ± 0.063 [ -1.0% .. +0.3%] samples 49 61 There's also no stat sig change in RSS (as measured by `time -l`): base diff difference (95% CI) time 998038627.097 ± 13567305.958 1003327715.556 ± 15210451.236 [ -0.2% .. +1.2%] samples 31 36 Reviewed By: #lld-macho, oontvoo Differential Revision: https://reviews.llvm.org/D118797
1 parent dbf47d2 commit 2b78ef0

File tree

9 files changed

+109
-104
lines changed

9 files changed

+109
-104
lines changed

lld/MachO/ConcatOutputSection.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ void ConcatOutputSection::finalize() {
313313
fatal(Twine(__FUNCTION__) + ": FIXME: thunk range overrun");
314314
}
315315
thunkInfo.isec =
316-
make<ConcatInputSection>(isec->getSegName(), isec->getName());
316+
makeSyntheticInputSection(isec->getSegName(), isec->getName());
317317
thunkInfo.isec->parent = this;
318318

319319
// This code runs after dead code removal. Need to set the `live` bit

lld/MachO/Driver.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -540,17 +540,19 @@ static void replaceCommonSymbols() {
540540
// but it's not really worth supporting the linking of 64-bit programs on
541541
// 32-bit archs.
542542
ArrayRef<uint8_t> data = {nullptr, static_cast<size_t>(common->size)};
543-
auto *isec = make<ConcatInputSection>(
544-
segment_names::data, section_names::common, common->getFile(), data,
545-
common->align, S_ZEROFILL);
543+
// FIXME avoid creating one Section per symbol?
544+
auto *section =
545+
make<Section>(common->getFile(), segment_names::data,
546+
section_names::common, S_ZEROFILL, /*addr=*/0);
547+
auto *isec = make<ConcatInputSection>(*section, data, common->align);
546548
if (!osec)
547549
osec = ConcatOutputSection::getOrCreateForInput(isec);
548550
isec->parent = osec;
549551
inputSections.push_back(isec);
550552

551553
// FIXME: CommonSymbol should store isReferencedDynamically, noDeadStrip
552554
// and pass them on here.
553-
replaceSymbol<Defined>(sym, sym->getName(), isec->getFile(), isec,
555+
replaceSymbol<Defined>(sym, sym->getName(), common->getFile(), isec,
554556
/*value=*/0,
555557
/*size=*/0,
556558
/*isWeakDef=*/false,
@@ -1005,8 +1007,8 @@ static void gatherInputSections() {
10051007
TimeTraceScope timeScope("Gathering input sections");
10061008
int inputOrder = 0;
10071009
for (const InputFile *file : inputFiles) {
1008-
for (const Section &section : file->sections) {
1009-
const Subsections &subsections = section.subsections;
1010+
for (const Section *section : file->sections) {
1011+
const Subsections &subsections = section->subsections;
10101012
if (subsections.empty())
10111013
continue;
10121014
if (subsections[0].isec->getName() == section_names::compactUnwind)

lld/MachO/InputFiles.cpp

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -277,28 +277,24 @@ void ObjFile::parseSections(ArrayRef<SectionHeader> sectionHeaders) {
277277
ArrayRef<uint8_t> data = {isZeroFill(sec.flags) ? nullptr
278278
: buf + sec.offset,
279279
static_cast<size_t>(sec.size)};
280-
sections.push_back(sec.addr);
280+
sections.push_back(make<Section>(this, segname, name, sec.flags, sec.addr));
281281
if (sec.align >= 32) {
282282
error("alignment " + std::to_string(sec.align) + " of section " + name +
283283
" is too large");
284284
continue;
285285
}
286+
const Section &section = *sections.back();
286287
uint32_t align = 1 << sec.align;
287-
uint32_t flags = sec.flags;
288288

289289
auto splitRecords = [&](int recordSize) -> void {
290290
if (data.empty())
291291
return;
292-
Subsections &subsections = sections.back().subsections;
292+
Subsections &subsections = sections.back()->subsections;
293293
subsections.reserve(data.size() / recordSize);
294-
auto *isec = make<ConcatInputSection>(
295-
segname, name, this, data.slice(0, recordSize), align, flags);
296-
subsections.push_back({0, isec});
297-
for (uint64_t off = recordSize; off < data.size(); off += recordSize) {
298-
// Copying requires less memory than constructing a fresh InputSection.
299-
auto *copy = make<ConcatInputSection>(*isec);
300-
copy->data = data.slice(off, recordSize);
301-
subsections.push_back({off, copy});
294+
for (uint64_t off = 0; off < data.size(); off += recordSize) {
295+
auto *isec = make<ConcatInputSection>(
296+
section, data.slice(off, recordSize), align);
297+
subsections.push_back({off, isec});
302298
}
303299
};
304300

@@ -312,19 +308,17 @@ void ObjFile::parseSections(ArrayRef<SectionHeader> sectionHeaders) {
312308

313309
InputSection *isec;
314310
if (sectionType(sec.flags) == S_CSTRING_LITERALS) {
315-
isec =
316-
make<CStringInputSection>(segname, name, this, data, align, flags);
311+
isec = make<CStringInputSection>(section, data, align);
317312
// FIXME: parallelize this?
318313
cast<CStringInputSection>(isec)->splitIntoPieces();
319314
} else {
320-
isec = make<WordLiteralInputSection>(segname, name, this, data, align,
321-
flags);
315+
isec = make<WordLiteralInputSection>(section, data, align);
322316
}
323-
sections.back().subsections.push_back({0, isec});
317+
sections.back()->subsections.push_back({0, isec});
324318
} else if (auto recordSize = getRecordSize(segname, name)) {
325319
splitRecords(*recordSize);
326320
if (name == section_names::compactUnwind)
327-
compactUnwindSection = &sections.back();
321+
compactUnwindSection = sections.back();
328322
} else if (segname == segment_names::llvm) {
329323
if (name == "__cg_profile" && config->callGraphProfileSort) {
330324
TimeTraceScope timeScope("Parsing call graph section");
@@ -352,16 +346,15 @@ void ObjFile::parseSections(ArrayRef<SectionHeader> sectionHeaders) {
352346
// spurious duplicate symbol errors, we do not parse these sections.
353347
// TODO: Evaluate whether the bitcode metadata is needed.
354348
} else {
355-
auto *isec =
356-
make<ConcatInputSection>(segname, name, this, data, align, flags);
349+
auto *isec = make<ConcatInputSection>(section, data, align);
357350
if (isDebugSection(isec->getFlags()) &&
358351
isec->getSegName() == segment_names::dwarf) {
359352
// Instead of emitting DWARF sections, we emit STABS symbols to the
360353
// object files that contain them. We filter them out early to avoid
361354
// parsing their relocations unnecessarily.
362355
debugSections.push_back(isec);
363356
} else {
364-
sections.back().subsections.push_back({0, isec});
357+
sections.back()->subsections.push_back({0, isec});
365358
}
366359
}
367360
}
@@ -506,7 +499,7 @@ void ObjFile::parseRelocations(ArrayRef<SectionHeader> sectionHeaders,
506499
referentOffset = totalAddend - referentSecHead.addr;
507500
}
508501
Subsections &referentSubsections =
509-
sections[relInfo.r_symbolnum - 1].subsections;
502+
sections[relInfo.r_symbolnum - 1]->subsections;
510503
r.referent =
511504
findContainingSubsection(referentSubsections, &referentOffset);
512505
r.addend = referentOffset;
@@ -547,7 +540,7 @@ void ObjFile::parseRelocations(ArrayRef<SectionHeader> sectionHeaders,
547540
uint64_t referentOffset =
548541
totalAddend - sectionHeaders[minuendInfo.r_symbolnum - 1].addr;
549542
Subsections &referentSubsectVec =
550-
sections[minuendInfo.r_symbolnum - 1].subsections;
543+
sections[minuendInfo.r_symbolnum - 1]->subsections;
551544
p.referent =
552545
findContainingSubsection(referentSubsectVec, &referentOffset);
553546
p.addend = referentOffset;
@@ -699,7 +692,7 @@ void ObjFile::parseSymbols(ArrayRef<typename LP::section> sectionHeaders,
699692

700693
StringRef name = strtab + sym.n_strx;
701694
if ((sym.n_type & N_TYPE) == N_SECT) {
702-
Subsections &subsections = sections[sym.n_sect - 1].subsections;
695+
Subsections &subsections = sections[sym.n_sect - 1]->subsections;
703696
// parseSections() may have chosen not to parse this section.
704697
if (subsections.empty())
705698
continue;
@@ -712,7 +705,7 @@ void ObjFile::parseSymbols(ArrayRef<typename LP::section> sectionHeaders,
712705
}
713706

714707
for (size_t i = 0; i < sections.size(); ++i) {
715-
Subsections &subsections = sections[i].subsections;
708+
Subsections &subsections = sections[i]->subsections;
716709
if (subsections.empty())
717710
continue;
718711
InputSection *lastIsec = subsections.back().isec;
@@ -823,12 +816,13 @@ OpaqueFile::OpaqueFile(MemoryBufferRef mb, StringRef segName,
823816
: InputFile(OpaqueKind, mb) {
824817
const auto *buf = reinterpret_cast<const uint8_t *>(mb.getBufferStart());
825818
ArrayRef<uint8_t> data = {buf, mb.getBufferSize()};
826-
ConcatInputSection *isec =
827-
make<ConcatInputSection>(segName.take_front(16), sectName.take_front(16),
828-
/*file=*/this, data);
819+
sections.push_back(make<Section>(/*file=*/this, segName.take_front(16),
820+
sectName.take_front(16),
821+
/*flags=*/0, /*addr=*/0));
822+
Section &section = *sections.back();
823+
ConcatInputSection *isec = make<ConcatInputSection>(section, data);
829824
isec->live = true;
830-
sections.push_back(0);
831-
sections.back().subsections.push_back({0, isec});
825+
section.subsections.push_back({0, isec});
832826
}
833827

834828
ObjFile::ObjFile(MemoryBufferRef mb, uint32_t modTime, StringRef archiveName,
@@ -898,9 +892,9 @@ template <class LP> void ObjFile::parse() {
898892
// The relocations may refer to the symbols, so we parse them after we have
899893
// parsed all the symbols.
900894
for (size_t i = 0, n = sections.size(); i < n; ++i)
901-
if (!sections[i].subsections.empty())
895+
if (!sections[i]->subsections.empty())
902896
parseRelocations(sectionHeaders, sectionHeaders[i],
903-
sections[i].subsections);
897+
sections[i]->subsections);
904898

905899
parseDebugInfo();
906900
if (compactUnwindSection)

lld/MachO/InputFiles.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,24 @@ struct Subsection {
5858
};
5959

6060
using Subsections = std::vector<Subsection>;
61+
class InputFile;
6162

6263
struct Section {
63-
uint64_t address = 0;
64+
InputFile *file;
65+
StringRef segname;
66+
StringRef name;
67+
uint32_t flags;
68+
uint64_t addr;
6469
Subsections subsections;
65-
Section(uint64_t addr) : address(addr){};
70+
71+
Section(InputFile *file, StringRef segname, StringRef name, uint32_t flags,
72+
uint64_t addr)
73+
: file(file), segname(segname), name(name), flags(flags), addr(addr) {}
74+
// Ensure pointers to Sections are never invalidated.
75+
Section(const Section &) = delete;
76+
Section &operator=(const Section &) = delete;
77+
Section(Section &&) = delete;
78+
Section &operator=(Section &&) = delete;
6679
};
6780

6881
// Represents a call graph profile edge.
@@ -93,7 +106,7 @@ class InputFile {
93106
MemoryBufferRef mb;
94107

95108
std::vector<Symbol *> symbols;
96-
std::vector<Section> sections;
109+
std::vector<Section *> sections;
97110

98111
// If not empty, this stores the name of the archive containing this file.
99112
// We use this string for creating error messages.

lld/MachO/InputSection.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,18 @@ void ConcatInputSection::writeTo(uint8_t *buf) {
177177
}
178178
}
179179

180+
ConcatInputSection *macho::makeSyntheticInputSection(StringRef segName,
181+
StringRef sectName,
182+
uint32_t flags,
183+
ArrayRef<uint8_t> data,
184+
uint32_t align) {
185+
Section &section =
186+
*make<Section>(/*file=*/nullptr, segName, sectName, flags, /*addr=*/0);
187+
auto isec = make<ConcatInputSection>(section, data, align);
188+
section.subsections.push_back({0, isec});
189+
return isec;
190+
}
191+
180192
void CStringInputSection::splitIntoPieces() {
181193
size_t off = 0;
182194
StringRef s = toStringRef(data);
@@ -211,13 +223,11 @@ uint64_t CStringInputSection::getOffset(uint64_t off) const {
211223
return piece.outSecOff + addend;
212224
}
213225

214-
WordLiteralInputSection::WordLiteralInputSection(StringRef segname,
215-
StringRef name,
216-
InputFile *file,
226+
WordLiteralInputSection::WordLiteralInputSection(const Section &section,
217227
ArrayRef<uint8_t> data,
218-
uint32_t align, uint32_t flags)
219-
: InputSection(WordLiteralKind, segname, name, file, data, align, flags) {
220-
switch (sectionType(flags)) {
228+
uint32_t align)
229+
: InputSection(WordLiteralKind, section, data, align) {
230+
switch (sectionType(getFlags())) {
221231
case S_4BYTE_LITERALS:
222232
power2LiteralSize = 2;
223233
break;

0 commit comments

Comments
 (0)