@@ -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,40 @@ 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 ;
17321730 // TODO: Call buildCStringPriorities() to support cstring ordering when
17331731 // deduplication is off, although this may negatively impact build
17341732 // performance.
17351733 for (CStringInputSection *isec : inputs) {
17361734 for (const auto &[i, piece] : llvm::enumerate (isec->pieces )) {
17371735 if (!piece.live )
17381736 continue ;
1739- uint32_t pieceAlign = 1 << getStringPieceAlignment (isec, piece);
1740- offset = alignToPowerOf2 (offset, pieceAlign);
1741- piece.outSecOff = offset;
1742- isec->isFinal = true ;
1737+ piece.outSecOff = alignTo (size, getStringPieceAlignment (isec, piece));
17431738 StringRef string = isec->getStringRef (i);
1744- offset += string.size () + 1 ; // account for null terminator
1739+ size = piece. outSecOff + string.size () + 1 ; // account for null terminator
17451740 }
1741+ isec->isFinal = true ;
17461742 }
1747- size = offset;
17481743}
17491744
17501745void DeduplicatedCStringSection::finalizeContents () {
17511746 // Find the largest alignment required for each string.
1747+ DenseMap<CachedHashStringRef, Align> strToAlignment;
17521748 for (const CStringInputSection *isec : inputs) {
17531749 for (const auto &[i, piece] : llvm::enumerate (isec->pieces )) {
17541750 if (!piece.live )
17551751 continue ;
17561752 auto s = isec->getCachedHashStringRef (i);
17571753 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;
1754+ auto align = getStringPieceAlignment (isec, piece);
1755+ auto [it, wasInserted] = strToAlignment.try_emplace (s, align);
1756+ if (!wasInserted && it->second < align)
1757+ it->second = align;
17631758 }
17641759 }
17651760
@@ -1769,38 +1764,31 @@ void DeduplicatedCStringSection::finalizeContents() {
17691764 for (auto &[isec, i] : priorityBuilder.buildCStringPriorities (inputs)) {
17701765 auto &piece = isec->pieces [i];
17711766 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
1767+ auto [it, wasInserted] = stringOffsetMap.try_emplace (s, /* placeholder*/ 0 );
1768+ if (wasInserted) {
1769+ // Avoid computing the offset until we are sure we will need to
1770+ uint64_t offset = alignTo (size, strToAlignment.at (s));
1771+ it->second = offset;
1772+ size = offset + s.size () + 1 ; // account for null terminator
17801773 }
1781- piece.outSecOff = offsetInfo.outSecOff ;
1774+ // If the string was already in stringOffsetMap, it is a duplicate and we
1775+ // only need to assign the offset.
1776+ piece.outSecOff = it->second ;
17821777 }
17831778 for (CStringInputSection *isec : inputs)
17841779 isec->isFinal = true ;
17851780}
17861781
17871782void 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- }
1783+ for (const auto &[s, outSecOff] : stringOffsetMap)
1784+ if (s.size ())
1785+ memcpy (buf + outSecOff, s.data (), s.size ());
17941786}
17951787
1796- DeduplicatedCStringSection::StringOffset
1797- DeduplicatedCStringSection::getStringOffset (StringRef str) const {
1788+ uint64_t DeduplicatedCStringSection::getStringOffset (StringRef str) const {
17981789 // StringPiece uses 31 bits to store the hashes, so we replicate that
17991790 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 ;
1791+ return stringOffsetMap.at (CachedHashStringRef (str, hash));
18041792}
18051793
18061794// This section is actually emitted as __TEXT,__const by ld64, but clang may
0 commit comments