@@ -848,8 +848,7 @@ void ObjCSelRefsHelper::initialize() {
848
848
void ObjCSelRefsHelper::cleanup () { methnameToSelref.clear (); }
849
849
850
850
ConcatInputSection *ObjCSelRefsHelper::makeSelRef (StringRef methname) {
851
- auto methnameOffset =
852
- in.objcMethnameSection ->getStringOffset (methname).outSecOff ;
851
+ auto methnameOffset = in.objcMethnameSection ->getStringOffset (methname);
853
852
854
853
size_t wordSize = target->wordSize ;
855
854
uint8_t *selrefData = bAlloc ().Allocate <uint8_t >(wordSize);
@@ -1722,44 +1721,41 @@ void CStringSection::writeTo(uint8_t *buf) const {
1722
1721
// and don't need this alignment. They will be emitted at some arbitrary address
1723
1722
// `A`, but ld64 will treat them as being 16-byte aligned with an offset of
1724
1723
// `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 ) );
1728
1727
}
1729
1728
1730
1729
void CStringSection::finalizeContents () {
1731
- uint64_t offset = 0 ;
1730
+ size = 0 ;
1732
1731
// TODO: Call buildCStringPriorities() to support cstring ordering when
1733
1732
// deduplication is off, although this may negatively impact build
1734
1733
// performance.
1735
1734
for (CStringInputSection *isec : inputs) {
1736
1735
for (const auto &[i, piece] : llvm::enumerate (isec->pieces )) {
1737
1736
if (!piece.live )
1738
1737
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));
1743
1739
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
1745
1741
}
1742
+ isec->isFinal = true ;
1746
1743
}
1747
- size = offset;
1748
1744
}
1749
1745
1750
1746
void DeduplicatedCStringSection::finalizeContents () {
1751
1747
// Find the largest alignment required for each string.
1748
+ DenseMap<CachedHashStringRef, Align> strToAlignment;
1752
1749
for (const CStringInputSection *isec : inputs) {
1753
1750
for (const auto &[i, piece] : llvm::enumerate (isec->pieces )) {
1754
1751
if (!piece.live )
1755
1752
continue ;
1756
1753
auto s = isec->getCachedHashStringRef (i);
1757
1754
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;
1763
1759
}
1764
1760
}
1765
1761
@@ -1769,38 +1765,31 @@ void DeduplicatedCStringSection::finalizeContents() {
1769
1765
for (auto &[isec, i] : priorityBuilder.buildCStringPriorities (inputs)) {
1770
1766
auto &piece = isec->pieces [i];
1771
1767
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
1780
1774
}
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 ;
1782
1778
}
1783
1779
for (CStringInputSection *isec : inputs)
1784
1780
isec->isFinal = true ;
1785
1781
}
1786
1782
1787
1783
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 ());
1794
1787
}
1795
1788
1796
- DeduplicatedCStringSection::StringOffset
1797
- DeduplicatedCStringSection::getStringOffset (StringRef str) const {
1789
+ uint64_t DeduplicatedCStringSection::getStringOffset (StringRef str) const {
1798
1790
// StringPiece uses 31 bits to store the hashes, so we replicate that
1799
1791
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));
1804
1793
}
1805
1794
1806
1795
// This section is actually emitted as __TEXT,__const by ld64, but clang may
0 commit comments