@@ -848,8 +848,7 @@ void ObjCSelRefsHelper::initialize() {
848848void ObjCSelRefsHelper::cleanup () { methnameToSelref.clear (); }
849849
850850ConcatInputSection *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
17301729void 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
17501746void 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
17871783void 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
0 commit comments