Define DefinedAtom::sectionSize.

Merge::mergeByLargestSection is half-baked since it's defined
in terms of section size, there's no way to get the section size
of an atom.

Currently we work around the issue by traversing the layout edges
to both directions and calculate the sum of all atoms reachable.
I wrote that code but I knew it's hacky. It's even not guaranteed
to work. If you add layout edges before the core linking, it
miscalculates a size.

Also it's of course slow. It's basically a linked list traversal.

In this patch I added DefinedAtom::sectionSize so that we can use
that for mergeByLargestSection. I'm not very happy to add a new
field to DefinedAtom base class, but I think it's legitimate since
mergeByLargestSection is defined for section size, and the section
size is currently just missing.

http://reviews.llvm.org/D7966

llvm-svn: 231290
This commit is contained in:
Rui Ueyama 2015-03-04 21:40:46 +00:00
parent 00fb6c9da0
commit 77a4da1991
9 changed files with 46 additions and 59 deletions

View File

@ -234,6 +234,13 @@ public:
/// For a function atom, it is the number of bytes of code in the function. /// For a function atom, it is the number of bytes of code in the function.
virtual uint64_t size() const = 0; virtual uint64_t size() const = 0;
/// \brief The size of the section from which the atom is instantiated.
///
/// Merge::mergeByLargestSection is defined in terms of section size
/// and not in terms of atom size, so we need this function separate
/// from size().
virtual uint64_t sectionSize() const { return 0; }
/// \brief The visibility of this atom to other atoms. /// \brief The visibility of this atom to other atoms.
/// ///
/// C static functions have scope scopeTranslationUnit. Regular C functions /// C static functions have scope scopeTranslationUnit. Regular C functions

View File

@ -133,36 +133,6 @@ static MergeResolution mergeSelect(DefinedAtom::Merge first,
return mergeCases[first][second]; 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<const DefinedAtom>(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) { bool SymbolTable::addByName(const Atom &newAtom) {
StringRef name = newAtom.name(); StringRef name = newAtom.name();
assert(!name.empty()); assert(!name.empty());
@ -198,14 +168,14 @@ bool SymbolTable::addByName(const Atom &newAtom) {
useNew = true; useNew = true;
break; break;
case MCR_Largest: { case MCR_Largest: {
uint64_t existingSize = sectionSize(existingDef); uint64_t existingSize = existingDef->sectionSize();
uint64_t newSize = sectionSize(newDef); uint64_t newSize = newDef->sectionSize();
useNew = (newSize >= existingSize); useNew = (newSize >= existingSize);
break; break;
} }
case MCR_SameSize: { case MCR_SameSize: {
uint64_t existingSize = sectionSize(existingDef); uint64_t existingSize = existingDef->sectionSize();
uint64_t newSize = sectionSize(newDef); uint64_t newSize = newDef->sectionSize();
if (existingSize == newSize) { if (existingSize == newSize) {
useNew = true; useNew = true;
break; break;

View File

@ -136,6 +136,7 @@ struct NativeDefinedAtomIvarsV1 {
uint32_t referencesCount; uint32_t referencesCount;
uint32_t contentOffset; uint32_t contentOffset;
uint32_t contentSize; uint32_t contentSize;
uint64_t sectionSize;
}; };

View File

@ -45,9 +45,9 @@ public:
StringRef name() const override; StringRef name() const override;
uint64_t size() const override { uint64_t size() const override { return _ivarData->contentSize; }
return _ivarData->contentSize;
} uint64_t sectionSize() const override { return _ivarData->sectionSize; }
DefinedAtom::Scope scope() const override { DefinedAtom::Scope scope() const override {
return (DefinedAtom::Scope)(attributes().scope); return (DefinedAtom::Scope)(attributes().scope);

View File

@ -126,6 +126,7 @@ private:
ivar.referencesCount = refsCount; ivar.referencesCount = refsCount;
ivar.contentOffset = getContentOffset(atom); ivar.contentOffset = getContentOffset(atom);
ivar.contentSize = atom.size(); ivar.contentSize = atom.size();
ivar.sectionSize = atom.sectionSize();
_definedAtomIvars.push_back(ivar); _definedAtomIvars.push_back(ivar);
} }

View File

@ -145,11 +145,12 @@ private:
class COFFDefinedFileAtom : public COFFBaseDefinedAtom { class COFFDefinedFileAtom : public COFFBaseDefinedAtom {
public: public:
COFFDefinedFileAtom(const File &file, StringRef name, StringRef sectionName, COFFDefinedFileAtom(const File &file, StringRef name, StringRef sectionName,
Scope scope, ContentType contentType, uint64_t sectionSize, Scope scope,
ContentPermissions perms, uint64_t ordinal) ContentType contentType, ContentPermissions perms,
uint64_t ordinal)
: COFFBaseDefinedAtom(file, name, Kind::File), _sectionName(sectionName), : COFFBaseDefinedAtom(file, name, Kind::File), _sectionName(sectionName),
_scope(scope), _contentType(contentType), _permissions(perms), _sectionSize(sectionSize), _scope(scope), _contentType(contentType),
_ordinal(ordinal), _alignment(0) {} _permissions(perms), _ordinal(ordinal), _alignment(0) {}
static bool classof(const COFFBaseDefinedAtom *atom) { static bool classof(const COFFBaseDefinedAtom *atom) {
return atom->getKind() == Kind::File; return atom->getKind() == Kind::File;
@ -158,6 +159,7 @@ public:
void setAlignment(Alignment val) { _alignment = val; } void setAlignment(Alignment val) { _alignment = val; }
SectionChoice sectionChoice() const override { return sectionCustomRequired; } SectionChoice sectionChoice() const override { return sectionCustomRequired; }
StringRef customSectionName() const override { return _sectionName; } StringRef customSectionName() const override { return _sectionName; }
uint64_t sectionSize() const override { return _sectionSize; }
Scope scope() const override { return _scope; } Scope scope() const override { return _scope; }
ContentType contentType() const override { return _contentType; } ContentType contentType() const override { return _contentType; }
ContentPermissions permissions() const override { return _permissions; } ContentPermissions permissions() const override { return _permissions; }
@ -173,6 +175,7 @@ public:
private: private:
StringRef _sectionName; StringRef _sectionName;
uint64_t _sectionSize;
Scope _scope; Scope _scope;
ContentType _contentType; ContentType _contentType;
ContentPermissions _permissions; ContentPermissions _permissions;
@ -185,11 +188,11 @@ private:
class COFFDefinedAtom : public COFFDefinedFileAtom { class COFFDefinedAtom : public COFFDefinedFileAtom {
public: public:
COFFDefinedAtom(const File &file, StringRef name, StringRef sectionName, COFFDefinedAtom(const File &file, StringRef name, StringRef sectionName,
Scope scope, ContentType type, bool isComdat, uint64_t sectionSize, Scope scope, ContentType type,
ContentPermissions perms, Merge merge, ArrayRef<uint8_t> data, bool isComdat, ContentPermissions perms, Merge merge,
uint64_t ordinal) ArrayRef<uint8_t> data, uint64_t ordinal)
: COFFDefinedFileAtom(file, name, sectionName, scope, type, perms, : COFFDefinedFileAtom(file, name, sectionName, sectionSize,
ordinal), scope, type, perms, ordinal),
_isComdat(isComdat), _merge(merge), _dataref(data) {} _isComdat(isComdat), _merge(merge), _dataref(data) {}
Merge merge() const override { return _merge; } Merge merge() const override { return _merge; }
@ -213,8 +216,8 @@ public:
COFFBSSAtom(const File &file, StringRef name, Scope scope, COFFBSSAtom(const File &file, StringRef name, Scope scope,
ContentPermissions perms, Merge merge, uint32_t size, ContentPermissions perms, Merge merge, uint32_t size,
uint64_t ordinal) uint64_t ordinal)
: COFFDefinedFileAtom(file, name, ".bss", scope, typeZeroFill, perms, : COFFDefinedFileAtom(file, name, ".bss", 0, scope, typeZeroFill,
ordinal), perms, ordinal),
_merge(merge), _size(size) {} _merge(merge), _size(size) {}
Merge merge() const override { return _merge; } Merge merge() const override { return _merge; }

View File

@ -694,14 +694,15 @@ std::error_code FileCOFF::AtomizeDefinedSymbolsInSection(
DefinedAtom::ContentType type = getContentType(section); DefinedAtom::ContentType type = getContentType(section);
DefinedAtom::ContentPermissions perms = getPermissions(section); DefinedAtom::ContentPermissions perms = getPermissions(section);
uint64_t sectionSize = section->SizeOfRawData;
bool isComdat = (_comdatSections.count(section) == 1); bool isComdat = (_comdatSections.count(section) == 1);
// Create an atom for the entire section. // Create an atom for the entire section.
if (symbols.empty()) { if (symbols.empty()) {
ArrayRef<uint8_t> data(secData.data(), secData.size()); ArrayRef<uint8_t> data(secData.data(), secData.size());
auto *atom = new (_alloc) COFFDefinedAtom( auto *atom = new (_alloc) COFFDefinedAtom(
*this, "", sectionName, Atom::scopeTranslationUnit, type, isComdat, *this, "", sectionName, sectionSize, Atom::scopeTranslationUnit,
perms, _merge[section], data, getNextOrdinal()); type, isComdat, perms, _merge[section], data, getNextOrdinal());
atoms.push_back(atom); atoms.push_back(atom);
_definedAtomLocations[section][0].push_back(atom); _definedAtomLocations[section][0].push_back(atom);
return std::error_code(); return std::error_code();
@ -713,8 +714,8 @@ std::error_code FileCOFF::AtomizeDefinedSymbolsInSection(
uint64_t size = symbols[0].getValue(); uint64_t size = symbols[0].getValue();
ArrayRef<uint8_t> data(secData.data(), size); ArrayRef<uint8_t> data(secData.data(), size);
auto *atom = new (_alloc) COFFDefinedAtom( auto *atom = new (_alloc) COFFDefinedAtom(
*this, "", sectionName, Atom::scopeTranslationUnit, type, isComdat, *this, "", sectionName, sectionSize, Atom::scopeTranslationUnit,
perms, _merge[section], data, getNextOrdinal()); type, isComdat, perms, _merge[section], data, getNextOrdinal());
atoms.push_back(atom); atoms.push_back(atom);
_definedAtomLocations[section][0].push_back(atom); _definedAtomLocations[section][0].push_back(atom);
} }
@ -726,8 +727,8 @@ std::error_code FileCOFF::AtomizeDefinedSymbolsInSection(
: secData.data() + (si + 1)->getValue(); : secData.data() + (si + 1)->getValue();
ArrayRef<uint8_t> data(start, end); ArrayRef<uint8_t> data(start, end);
auto *atom = new (_alloc) COFFDefinedAtom( auto *atom = new (_alloc) COFFDefinedAtom(
*this, _symbolName[*si], sectionName, getScope(*si), type, isComdat, *this, _symbolName[*si], sectionName, sectionSize, getScope(*si),
perms, _merge[section], data, getNextOrdinal()); type, isComdat, perms, _merge[section], data, getNextOrdinal());
atoms.push_back(atom); atoms.push_back(atom);
_symbolAtom[*si] = atom; _symbolAtom[*si] = atom;
_definedAtomLocations[section][si->getValue()].push_back(atom); _definedAtomLocations[section][si->getValue()].push_back(atom);
@ -982,9 +983,9 @@ std::error_code FileCOFF::maybeCreateSXDataAtoms() {
return std::error_code(); return std::error_code();
auto *atom = new (_alloc) COFFDefinedAtom( auto *atom = new (_alloc) COFFDefinedAtom(
*this, "", ".sxdata", Atom::scopeTranslationUnit, DefinedAtom::typeData, *this, "", ".sxdata", 0, Atom::scopeTranslationUnit,
false /*isComdat*/, DefinedAtom::permR__, DefinedAtom::mergeNo, DefinedAtom::typeData, false /*isComdat*/, DefinedAtom::permR__,
sxdata, getNextOrdinal()); DefinedAtom::mergeNo, sxdata, getNextOrdinal());
const ulittle32_t *symbolIndex = const ulittle32_t *symbolIndex =
reinterpret_cast<const ulittle32_t *>(sxdata.data()); reinterpret_cast<const ulittle32_t *>(sxdata.data());

View File

@ -814,7 +814,8 @@ template <> struct MappingTraits<const lld::DefinedAtom *> {
_deadStrip(atom->deadStrip()), _dynamicExport(atom->dynamicExport()), _deadStrip(atom->deadStrip()), _dynamicExport(atom->dynamicExport()),
_codeModel(atom->codeModel()), _codeModel(atom->codeModel()),
_permissions(atom->permissions()), _size(atom->size()), _permissions(atom->permissions()), _size(atom->size()),
_sectionName(atom->customSectionName()) { _sectionName(atom->customSectionName()),
_sectionSize(atom->sectionSize()) {
for (const lld::Reference *r : *atom) for (const lld::Reference *r : *atom)
_references.push_back(r); _references.push_back(r);
if (!atom->occupiesDiskSpace()) if (!atom->occupiesDiskSpace())
@ -860,6 +861,7 @@ template <> struct MappingTraits<const lld::DefinedAtom *> {
Alignment alignment() const override { return _alignment; } Alignment alignment() const override { return _alignment; }
SectionChoice sectionChoice() const override { return _sectionChoice; } SectionChoice sectionChoice() const override { return _sectionChoice; }
StringRef customSectionName() const override { return _sectionName; } StringRef customSectionName() const override { return _sectionName; }
uint64_t sectionSize() const override { return _sectionSize; }
SectionPosition sectionPosition() const override { return _sectionPosition; } SectionPosition sectionPosition() const override { return _sectionPosition; }
DeadStripKind deadStrip() const override { return _deadStrip; } DeadStripKind deadStrip() const override { return _deadStrip; }
DynamicExport dynamicExport() const override { return _dynamicExport; } DynamicExport dynamicExport() const override { return _dynamicExport; }
@ -915,6 +917,7 @@ template <> struct MappingTraits<const lld::DefinedAtom *> {
std::vector<ImplicitHex8> _content; std::vector<ImplicitHex8> _content;
uint64_t _size; uint64_t _size;
StringRef _sectionName; StringRef _sectionName;
uint64_t _sectionSize;
std::vector<const lld::Reference *> _references; std::vector<const lld::Reference *> _references;
bool _isGroupChild; bool _isGroupChild;
}; };
@ -953,6 +956,7 @@ template <> struct MappingTraits<const lld::DefinedAtom *> {
io.mapOptional("section-name", keys->_sectionName, StringRef()); io.mapOptional("section-name", keys->_sectionName, StringRef());
io.mapOptional("section-position", keys->_sectionPosition, io.mapOptional("section-position", keys->_sectionPosition,
DefinedAtom::sectionPositionAny); DefinedAtom::sectionPositionAny);
io.mapOptional("section-size", keys->_sectionSize, (uint64_t)0);
io.mapOptional("dead-strip", keys->_deadStrip, io.mapOptional("dead-strip", keys->_deadStrip,
DefinedAtom::deadStripNormal); DefinedAtom::deadStripNormal);
io.mapOptional("dynamic-export", keys->_dynamicExport, io.mapOptional("dynamic-export", keys->_dynamicExport,

View File

@ -15,7 +15,7 @@ symbols:
ComplexType: IMAGE_SYM_DTYPE_NULL ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition: SectionDefinition:
Length: 7 Length: 2
NumberOfRelocations: 0 NumberOfRelocations: 0
NumberOfLinenumbers: 0 NumberOfLinenumbers: 0
CheckSum: 2532800969 CheckSum: 2532800969