Skip to content

Commit

Permalink
Make dead-striping to handle reverse edges.
Browse files Browse the repository at this point in the history
Layout-before edges are no longer used for layout, but they are
still there for dead-stripping. If we would just remove them
from code, LLD would wrongly remove live atoms that were
referenced by layout-befores.

This patch fixes the issue. Before dead-stripping, it scans all
atoms to construct a reverse map for layout-after edges. Dead-
stripping pass uses the map to traverse the graph.

Differential Revision: http://reviews.llvm.org/D3986

llvm-svn: 210057
  • Loading branch information
rui314 committed Jun 3, 2014
1 parent f39d914 commit 23487e8
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 5 deletions.
13 changes: 10 additions & 3 deletions lld/include/lld/Core/Reference.h
Expand Up @@ -36,6 +36,12 @@ class Atom;
/// means R_X86_64_32 for x86_64, and R_386_GOTPC for i386. For PE/COFF
/// relocation 10 means IMAGE_REL_AMD64_SECTION.
///
/// References and atoms form a directed graph. The dead-stripping pass
/// traverses them starting from dead-strip root atoms to garbage collect
/// unreachable ones.
///
/// References of any kind are considered as directed edges. In addition to
/// that, references of some kind is considered as bidirected edges.
class Reference {
public:
/// Which universe defines the kindValue().
Expand Down Expand Up @@ -77,10 +83,11 @@ class Reference {
/// KindValues used with KindNamespace::all and KindArch::all.
enum {
kindInGroup = 1,
// kindLayoutAfter is treated as a bidirected edge by the dead-stripping
// pass.
kindLayoutAfter = 2,
// kindLayoutBefore is currently used only by dead-stripping pass in
// the Resolver. Will be removed soon. To enforce layout, use
// kindLayoutAfter instead.
// kindLayoutBefore is currently used only by PECOFF port, and will
// be removed soon. To enforce layout, use kindLayoutAfter instead.
kindLayoutBefore = 3,
kindGroupChild = 4,
kindGroupParent = 5
Expand Down
2 changes: 2 additions & 0 deletions lld/include/lld/Core/Resolver.h
Expand Up @@ -14,6 +14,7 @@
#include "lld/Core/SharedLibraryFile.h"
#include "lld/Core/SymbolTable.h"

#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"

#include <set>
Expand Down Expand Up @@ -105,6 +106,7 @@ class Resolver {
std::set<const Atom *> _deadStripRoots;
llvm::DenseSet<const Atom *> _liveAtoms;
std::unique_ptr<MergedFile> _result;
llvm::DenseMap<const Atom *, llvm::DenseSet<const Atom *>> _reverseRef;
};

} // namespace lld
Expand Down
19 changes: 17 additions & 2 deletions lld/lib/Core/Resolver.cpp
Expand Up @@ -312,9 +312,17 @@ void Resolver::markLive(const Atom *atom) {
return;

// Mark all atoms it references as live
if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom))
if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom)) {
for (const Reference *ref : *defAtom)
markLive(ref->target());
for (const Atom *target : _reverseRef[defAtom])
markLive(target);
}
}

static bool isBackref(const Reference *ref) {
return ref->kindNamespace() == lld::Reference::KindNamespace::all &&
ref->kindValue() == lld::Reference::kindLayoutBefore;
}

// remove all atoms not actually used
Expand All @@ -323,7 +331,14 @@ void Resolver::deadStripOptimize() {
// only do this optimization with -dead_strip
if (!_context.deadStrip())
return;
assert(_liveAtoms.empty());

// Some type of references prevent referring atoms to be dead-striped.
// Make a reverse map of such references before traversing the graph.
for (const Atom *atom : _atoms)
if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom))
for (const Reference *ref : *defAtom)
if (isBackref(ref))
_reverseRef[ref->target()].insert(atom);

// By default, shared libraries are built with all globals as dead strip roots
if (_context.globalsAreDeadStripRoots())
Expand Down
25 changes: 25 additions & 0 deletions lld/test/core/dead-strip-reverse.objtxt
@@ -0,0 +1,25 @@
# RUN: lld -core --dead-strip %s | FileCheck -check-prefix=CHECK1 %s
# RUN: lld -core %s | FileCheck -check-prefix=CHECK2 %s

---
defined-atoms:
- name: entry
dead-strip: never
scope: global
references:
- kind: layout-after
offset: 0
target: def
- name: def
scope: global
- name: dead
scope: global
...

# CHECK1: name: entry
# CHECK1: name: def
# CHECK1-NOT: name: dead

# CHECK2: name: entry
# CHECK2: name: def
# CHECK2: name: dead

0 comments on commit 23487e8

Please sign in to comment.