Skip to content

Commit dd43a79

Browse files
authored
[lld][MachO] Use llvm::Align and remove StringOffset type (#161253)
Use `llvm::Align` instead of directly storing the shift amount for clarity. Also remove the `DeduplicatedCStringSection::StringOffset` in favor of simply storing the `uint64_t` offset since `trailingZeros` is not used outside of `finalizeContents()`. These two changes allow us to refactor `finalizeContents()`. No function change intended. Depends on #161241.
1 parent 9fd09f4 commit dd43a79

File tree

2 files changed

+29
-48
lines changed

2 files changed

+29
-48
lines changed

lld/MachO/SyntheticSections.cpp

Lines changed: 27 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -848,8 +848,7 @@ void ObjCSelRefsHelper::initialize() {
848848
void ObjCSelRefsHelper::cleanup() { methnameToSelref.clear(); }
849849

850850
ConcatInputSection *ObjCSelRefsHelper::makeSelRef(StringRef methname) {
851-
auto methnameOffset =
852-
in.objcMethnameSection->getStringOffset(methname).outSecOff;
851+
auto methnameOffset = in.objcMethnameSection->getStringOffset(methname);
853852

854853
size_t wordSize = target->wordSize;
855854
uint8_t *selrefData = bAlloc().Allocate<uint8_t>(wordSize);
@@ -1722,44 +1721,41 @@ void CStringSection::writeTo(uint8_t *buf) const {
17221721
// and don't need this alignment. They will be emitted at some arbitrary address
17231722
// `A`, but ld64 will treat them as being 16-byte aligned with an offset of
17241723
// `16 % A`.
1725-
static uint8_t getStringPieceAlignment(const CStringInputSection *isec,
1726-
const StringPiece &piece) {
1727-
return llvm::countr_zero(isec->align | piece.inSecOff);
1724+
static Align getStringPieceAlignment(const CStringInputSection *isec,
1725+
const StringPiece &piece) {
1726+
return llvm::Align(1ULL << llvm::countr_zero(isec->align | piece.inSecOff));
17281727
}
17291728

17301729
void CStringSection::finalizeContents() {
1731-
uint64_t offset = 0;
1730+
size = 0;
17321731
// TODO: Call buildCStringPriorities() to support cstring ordering when
17331732
// deduplication is off, although this may negatively impact build
17341733
// performance.
17351734
for (CStringInputSection *isec : inputs) {
17361735
for (const auto &[i, piece] : llvm::enumerate(isec->pieces)) {
17371736
if (!piece.live)
17381737
continue;
1739-
uint32_t pieceAlign = 1 << getStringPieceAlignment(isec, piece);
1740-
offset = alignToPowerOf2(offset, pieceAlign);
1741-
piece.outSecOff = offset;
1742-
isec->isFinal = true;
1738+
piece.outSecOff = alignTo(size, getStringPieceAlignment(isec, piece));
17431739
StringRef string = isec->getStringRef(i);
1744-
offset += string.size() + 1; // account for null terminator
1740+
size = piece.outSecOff + string.size() + 1; // account for null terminator
17451741
}
1742+
isec->isFinal = true;
17461743
}
1747-
size = offset;
17481744
}
17491745

17501746
void DeduplicatedCStringSection::finalizeContents() {
17511747
// Find the largest alignment required for each string.
1748+
DenseMap<CachedHashStringRef, Align> strToAlignment;
17521749
for (const CStringInputSection *isec : inputs) {
17531750
for (const auto &[i, piece] : llvm::enumerate(isec->pieces)) {
17541751
if (!piece.live)
17551752
continue;
17561753
auto s = isec->getCachedHashStringRef(i);
17571754
assert(isec->align != 0);
1758-
uint8_t trailingZeros = getStringPieceAlignment(isec, piece);
1759-
auto it = stringOffsetMap.insert(
1760-
std::make_pair(s, StringOffset(trailingZeros)));
1761-
if (!it.second && it.first->second.trailingZeros < trailingZeros)
1762-
it.first->second.trailingZeros = trailingZeros;
1755+
auto align = getStringPieceAlignment(isec, piece);
1756+
auto [it, wasInserted] = strToAlignment.try_emplace(s, align);
1757+
if (!wasInserted && it->second < align)
1758+
it->second = align;
17631759
}
17641760
}
17651761

@@ -1769,38 +1765,31 @@ void DeduplicatedCStringSection::finalizeContents() {
17691765
for (auto &[isec, i] : priorityBuilder.buildCStringPriorities(inputs)) {
17701766
auto &piece = isec->pieces[i];
17711767
auto s = isec->getCachedHashStringRef(i);
1772-
auto it = stringOffsetMap.find(s);
1773-
assert(it != stringOffsetMap.end());
1774-
lld::macho::DeduplicatedCStringSection::StringOffset &offsetInfo =
1775-
it->second;
1776-
if (offsetInfo.outSecOff == UINT64_MAX) {
1777-
offsetInfo.outSecOff =
1778-
alignToPowerOf2(size, 1ULL << offsetInfo.trailingZeros);
1779-
size = offsetInfo.outSecOff + s.size() + 1; // account for null terminator
1768+
auto [it, wasInserted] = stringOffsetMap.try_emplace(s, /*placeholder*/ 0);
1769+
if (wasInserted) {
1770+
// Avoid computing the offset until we are sure we will need to
1771+
uint64_t offset = alignTo(size, strToAlignment.at(s));
1772+
it->second = offset;
1773+
size = offset + s.size() + 1; // account for null terminator
17801774
}
1781-
piece.outSecOff = offsetInfo.outSecOff;
1775+
// If the string was already in stringOffsetMap, it is a duplicate and we
1776+
// only need to assign the offset.
1777+
piece.outSecOff = it->second;
17821778
}
17831779
for (CStringInputSection *isec : inputs)
17841780
isec->isFinal = true;
17851781
}
17861782

17871783
void DeduplicatedCStringSection::writeTo(uint8_t *buf) const {
1788-
for (const auto &p : stringOffsetMap) {
1789-
StringRef data = p.first.val();
1790-
uint64_t off = p.second.outSecOff;
1791-
if (!data.empty())
1792-
memcpy(buf + off, data.data(), data.size());
1793-
}
1784+
for (const auto &[s, outSecOff] : stringOffsetMap)
1785+
if (s.size())
1786+
memcpy(buf + outSecOff, s.data(), s.size());
17941787
}
17951788

1796-
DeduplicatedCStringSection::StringOffset
1797-
DeduplicatedCStringSection::getStringOffset(StringRef str) const {
1789+
uint64_t DeduplicatedCStringSection::getStringOffset(StringRef str) const {
17981790
// StringPiece uses 31 bits to store the hashes, so we replicate that
17991791
uint32_t hash = xxh3_64bits(str) & 0x7fffffff;
1800-
auto offset = stringOffsetMap.find(CachedHashStringRef(str, hash));
1801-
assert(offset != stringOffsetMap.end() &&
1802-
"Looked-up strings should always exist in section");
1803-
return offset->second;
1792+
return stringOffsetMap.at(CachedHashStringRef(str, hash));
18041793
}
18051794

18061795
// This section is actually emitted as __TEXT,__const by ld64, but clang may

lld/MachO/SyntheticSections.h

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -571,18 +571,10 @@ class DeduplicatedCStringSection final : public CStringSection {
571571
uint64_t getSize() const override { return size; }
572572
void finalizeContents() override;
573573
void writeTo(uint8_t *buf) const override;
574-
575-
struct StringOffset {
576-
uint8_t trailingZeros;
577-
uint64_t outSecOff = UINT64_MAX;
578-
579-
explicit StringOffset(uint8_t zeros) : trailingZeros(zeros) {}
580-
};
581-
582-
StringOffset getStringOffset(StringRef str) const;
574+
uint64_t getStringOffset(StringRef str) const;
583575

584576
private:
585-
llvm::DenseMap<llvm::CachedHashStringRef, StringOffset> stringOffsetMap;
577+
llvm::DenseMap<llvm::CachedHashStringRef, uint64_t> stringOffsetMap;
586578
size_t size = 0;
587579
};
588580

0 commit comments

Comments
 (0)