Index: include/lld/Core/DefinedAtom.h =================================================================== --- include/lld/Core/DefinedAtom.h +++ include/lld/Core/DefinedAtom.h @@ -255,6 +255,10 @@ /// \brief constraints on whether the linker may dead strip away this atom. virtual SectionPosition sectionPosition() const = 0; + /// \brief If merge() == mergeByLargestSection, this returns the + /// size of the section for this atom. + virtual uint64_t sectionSize() const { return 0; } + /// \brief constraints on whether the linker may dead strip away this atom. virtual DeadStripKind deadStrip() const = 0; Index: lib/Core/SymbolTable.cpp =================================================================== --- lib/Core/SymbolTable.cpp +++ lib/Core/SymbolTable.cpp @@ -135,36 +135,6 @@ return mergeCases[first][second]; } -static const DefinedAtom *followReference(const DefinedAtom *atom, - uint32_t kind) { - for (const Reference *r : *atom) - if (r->kindNamespace() == Reference::KindNamespace::all && - r->kindArch() == Reference::KindArch::all && - r->kindValue() == kind) - return cast(r->target()); - return nullptr; -} - -static uint64_t getSizeFollowReferences(const DefinedAtom *atom, - uint32_t kind) { - uint64_t size = 0; - for (;;) { - atom = followReference(atom, kind); - if (!atom) - return size; - size += atom->size(); - } -} - -// Returns the size of the section containing the given atom. Atoms in the same -// section are connected by layout-before and layout-after edges, so this -// function traverses them to get the total size of atoms in the same section. -static uint64_t sectionSize(const DefinedAtom *atom) { - return atom->size() - + getSizeFollowReferences(atom, lld::Reference::kindLayoutBefore) - + getSizeFollowReferences(atom, lld::Reference::kindLayoutAfter); -} - bool SymbolTable::addByName(const Atom &newAtom) { StringRef name = newAtom.name(); assert(!name.empty()); @@ -200,14 +170,14 @@ useNew = true; break; case MCR_Largest: { - uint64_t existingSize = sectionSize((DefinedAtom*)existing); - uint64_t newSize = sectionSize((DefinedAtom*)&newAtom); + uint64_t existingSize = ((DefinedAtom*)existing)->sectionSize(); + uint64_t newSize = ((DefinedAtom*)&newAtom)->sectionSize(); useNew = (newSize >= existingSize); break; } case MCR_SameSize: { - uint64_t existingSize = sectionSize((DefinedAtom*)existing); - uint64_t newSize = sectionSize((DefinedAtom*)&newAtom); + uint64_t existingSize = ((DefinedAtom*)existing)->sectionSize(); + uint64_t newSize = ((DefinedAtom*)&newAtom)->sectionSize(); if (existingSize == newSize) { useNew = true; break; Index: lib/ReaderWriter/PECOFF/Atoms.h =================================================================== --- lib/ReaderWriter/PECOFF/Atoms.h +++ lib/ReaderWriter/PECOFF/Atoms.h @@ -182,16 +182,19 @@ public: COFFDefinedAtom(const File &file, StringRef name, StringRef sectionName, Scope scope, ContentType type, bool isComdat, - ContentPermissions perms, Merge merge, ArrayRef data, - uint64_t ordinal) + ContentPermissions perms, Merge merge, uint64_t sectionSize, + ArrayRef data, uint64_t ordinal) : COFFDefinedFileAtom(file, name, sectionName, scope, type, perms, ordinal), - _isComdat(isComdat), _merge(merge), _dataref(data) {} + _isComdat(isComdat), _merge(merge), _sectionSize(sectionSize), + _dataref(data) {} Merge merge() const override { return _merge; } uint64_t size() const override { return _dataref.size(); } ArrayRef rawContent() const override { return _dataref; } + uint64_t sectionSize() const override { return _sectionSize; } + DeadStripKind deadStrip() const override { // Only COMDAT symbols would be dead-stripped. return _isComdat ? deadStripNormal : deadStripNever; @@ -200,6 +203,7 @@ private: bool _isComdat; Merge _merge; + uint64_t _sectionSize; ArrayRef _dataref; }; Index: lib/ReaderWriter/PECOFF/ReaderCOFF.cpp =================================================================== --- lib/ReaderWriter/PECOFF/ReaderCOFF.cpp +++ lib/ReaderWriter/PECOFF/ReaderCOFF.cpp @@ -636,7 +636,7 @@ ArrayRef data(secData.data(), secData.size()); auto *atom = new (_alloc) COFFDefinedAtom( *this, "", sectionName, Atom::scopeTranslationUnit, type, isComdat, - perms, _merge[section], data, _ordinal++); + perms, _merge[section], section->SizeOfRawData, data, _ordinal++); atoms.push_back(atom); _definedAtomLocations[section][0].push_back(atom); return error_code(); @@ -649,7 +649,7 @@ ArrayRef data(secData.data(), size); auto *atom = new (_alloc) COFFDefinedAtom( *this, "", sectionName, Atom::scopeTranslationUnit, type, isComdat, - perms, _merge[section], data, _ordinal++); + perms, _merge[section], section->SizeOfRawData, data, _ordinal++); atoms.push_back(atom); _definedAtomLocations[section][0].push_back(atom); } @@ -662,7 +662,7 @@ ArrayRef data(start, end); auto *atom = new (_alloc) COFFDefinedAtom( *this, _symbolName[*si], sectionName, getScope(*si), type, isComdat, - perms, _merge[section], data, _ordinal++); + perms, _merge[section], section->SizeOfRawData, data, _ordinal++); atoms.push_back(atom); _symbolAtom[*si] = atom; _definedAtomLocations[section][(*si)->Value].push_back(atom); @@ -834,7 +834,7 @@ auto *atom = new (_alloc) COFFDefinedAtom( *this, "", ".sxdata", Atom::scopeTranslationUnit, DefinedAtom::typeData, false /*isComdat*/, DefinedAtom::permR__, DefinedAtom::mergeNo, - atomContent, _ordinal++); + 0 /* sectionSize */, atomContent, _ordinal++); const ulittle32_t *symbolIndex = reinterpret_cast(sxdata.data());