summaryrefslogtreecommitdiffstats
path: root/lld/include
diff options
context:
space:
mode:
Diffstat (limited to 'lld/include')
-rw-r--r--lld/include/lld/Core/Atom.h51
-rw-r--r--lld/include/lld/Core/DefinedAtom.h2
-rw-r--r--lld/include/lld/Core/File.h99
-rw-r--r--lld/include/lld/Core/Resolver.h13
-rw-r--r--lld/include/lld/Core/SharedLibraryAtom.h2
-rw-r--r--lld/include/lld/Core/SharedLibraryFile.h17
-rw-r--r--lld/include/lld/Core/Simple.h59
-rw-r--r--lld/include/lld/Core/UndefinedAtom.h2
8 files changed, 201 insertions, 44 deletions
diff --git a/lld/include/lld/Core/Atom.h b/lld/include/lld/Core/Atom.h
index 27fdde022ba..cab89ef5296 100644
--- a/lld/include/lld/Core/Atom.h
+++ b/lld/include/lld/Core/Atom.h
@@ -16,6 +16,9 @@ namespace lld {
class File;
+template<typename T>
+class OwningAtomPtr;
+
///
/// The linker has a Graph Theory model of linking. An object file is seen
/// as a set of Atoms with References to other Atoms. Each Atom is a node
@@ -24,6 +27,7 @@ class File;
/// undefined symbol (extern declaration).
///
class Atom {
+ template<typename T> friend class OwningAtomPtr;
public:
/// Whether this atom is defined or a proxy for an undefined symbol
enum Definition {
@@ -71,6 +75,53 @@ private:
Definition _definition;
};
+/// Class which owns an atom pointer and runs the atom destructor when the
+/// owning pointer goes out of scope.
+template<typename T>
+class OwningAtomPtr {
+private:
+ OwningAtomPtr(const OwningAtomPtr &) = delete;
+ void operator=(const OwningAtomPtr&) = delete;
+public:
+ OwningAtomPtr() : atom(nullptr) { }
+ OwningAtomPtr(T *atom) : atom(atom) { }
+
+ ~OwningAtomPtr() {
+ if (atom)
+ runDestructor(atom);
+ }
+
+ void runDestructor(Atom *atom) {
+ atom->~Atom();
+ }
+
+ OwningAtomPtr(OwningAtomPtr &&ptr) : atom(ptr.atom) {
+ ptr.atom = nullptr;
+ }
+
+ void operator=(OwningAtomPtr&& ptr) {
+ atom = ptr.atom;
+ ptr.atom = nullptr;
+ }
+
+ T *const &get() const {
+ return atom;
+ }
+
+ T *&get() {
+ return atom;
+ }
+
+ T *release() {
+ auto *v = atom;
+ atom = nullptr;
+ return v;
+ }
+
+private:
+ T *atom;
+};
+
} // namespace lld
#endif // LLD_CORE_ATOM_H
diff --git a/lld/include/lld/Core/DefinedAtom.h b/lld/include/lld/Core/DefinedAtom.h
index 4a4d1c757fd..e3193f8aaf2 100644
--- a/lld/include/lld/Core/DefinedAtom.h
+++ b/lld/include/lld/Core/DefinedAtom.h
@@ -363,6 +363,8 @@ protected:
// constructor.
DefinedAtom() : Atom(definitionRegular) { }
+ ~DefinedAtom() override = default;
+
/// \brief Returns a pointer to the Reference object that the abstract
/// iterator "points" to.
virtual const Reference *derefIterator(const void *iter) const = 0;
diff --git a/lld/include/lld/Core/File.h b/lld/include/lld/Core/File.h
index f6e7d7eac10..eb41fcc38d9 100644
--- a/lld/include/lld/Core/File.h
+++ b/lld/include/lld/Core/File.h
@@ -15,6 +15,7 @@
#include "lld/Core/SharedLibraryAtom.h"
#include "lld/Core/UndefinedAtom.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/ErrorHandling.h"
#include <functional>
@@ -39,6 +40,10 @@ class LinkingContext;
/// The Atom objects in a File are owned by the File object. The Atom objects
/// are destroyed when the File object is destroyed.
class File {
+protected:
+ /// The type of atom mutable container.
+ template <typename T> using AtomVector = std::vector<OwningAtomPtr<T>>;
+
public:
virtual ~File();
@@ -104,18 +109,67 @@ public:
return _allocator;
}
- /// The type of atom mutable container.
- template <typename T> using AtomVector = std::vector<const T *>;
-
- /// The range type for the atoms. It's backed by a std::vector, but hides
- /// its member functions so that you can only call begin or end.
+ /// The range type for the atoms.
template <typename T> class AtomRange {
public:
- AtomRange(AtomVector<T> v) : _v(v) {}
- typename AtomVector<T>::const_iterator begin() const { return _v.begin(); }
- typename AtomVector<T>::const_iterator end() const { return _v.end(); }
- typename AtomVector<T>::iterator begin() { return _v.begin(); }
- typename AtomVector<T>::iterator end() { return _v.end(); }
+ AtomRange(AtomVector<T> &v) : _v(v) {}
+ AtomRange(const AtomVector<T> &v) : _v(const_cast<AtomVector<T> &>(v)) {}
+
+ typedef std::pointer_to_unary_function<const OwningAtomPtr<T>&,
+ const T*> ConstDerefFn;
+
+ typedef std::pointer_to_unary_function<OwningAtomPtr<T>&, T*> DerefFn;
+
+ typedef llvm::mapped_iterator<typename AtomVector<T>::const_iterator,
+ ConstDerefFn> ConstItTy;
+ typedef llvm::mapped_iterator<typename AtomVector<T>::iterator,
+ DerefFn> ItTy;
+
+ static const T* DerefConst(const OwningAtomPtr<T> &p) {
+ return p.get();
+ }
+
+ static T* Deref(OwningAtomPtr<T> &p) {
+ return p.get();
+ }
+
+ ConstItTy begin() const {
+ return ConstItTy(_v.begin(), ConstDerefFn(DerefConst));
+ }
+ ConstItTy end() const {
+ return ConstItTy(_v.end(), ConstDerefFn(DerefConst));
+ }
+
+ ItTy begin() {
+ return ItTy(_v.begin(), DerefFn(Deref));
+ }
+ ItTy end() {
+ return ItTy(_v.end(), DerefFn(Deref));
+ }
+
+ llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() {
+ return llvm::make_range(_v.begin(), _v.end());
+ }
+
+ llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() const {
+ return llvm::make_range(_v.begin(), _v.end());
+ }
+
+ bool empty() const {
+ return _v.empty();
+ }
+
+ size_t size() const {
+ return _v.size();
+ }
+
+ const OwningAtomPtr<T> &operator[](size_t idx) const {
+ return _v[idx];
+ }
+
+ OwningAtomPtr<T> &operator[](size_t idx) {
+ return _v[idx];
+ }
private:
AtomVector<T> &_v;
@@ -123,19 +177,25 @@ public:
/// \brief Must be implemented to return the AtomVector object for
/// all DefinedAtoms in this File.
- virtual const AtomVector<DefinedAtom> &defined() const = 0;
+ virtual const AtomRange<DefinedAtom> defined() const = 0;
/// \brief Must be implemented to return the AtomVector object for
/// all UndefinedAtomw in this File.
- virtual const AtomVector<UndefinedAtom> &undefined() const = 0;
+ virtual const AtomRange<UndefinedAtom> undefined() const = 0;
/// \brief Must be implemented to return the AtomVector object for
/// all SharedLibraryAtoms in this File.
- virtual const AtomVector<SharedLibraryAtom> &sharedLibrary() const = 0;
+ virtual const AtomRange<SharedLibraryAtom> sharedLibrary() const = 0;
/// \brief Must be implemented to return the AtomVector object for
/// all AbsoluteAtoms in this File.
- virtual const AtomVector<AbsoluteAtom> &absolute() const = 0;
+ virtual const AtomRange<AbsoluteAtom> absolute() const = 0;
+
+ /// Drop all of the atoms owned by this file. This will result in all of
+ /// the atoms running their destructors.
+ /// This is required because atoms may be allocated on a BumpPtrAllocator
+ /// of a different file. We need to destruct all atoms before any files.
+ virtual void clearAtoms() = 0;
/// \brief If a file is parsed using a different method than doParse(),
/// one must use this method to set the last error status, so that
@@ -194,19 +254,22 @@ public:
std::error_code doParse() override { return _ec; }
- const AtomVector<DefinedAtom> &defined() const override {
+ const AtomRange<DefinedAtom> defined() const override {
llvm_unreachable("internal error");
}
- const AtomVector<UndefinedAtom> &undefined() const override {
+ const AtomRange<UndefinedAtom> undefined() const override {
llvm_unreachable("internal error");
}
- const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+ const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
llvm_unreachable("internal error");
}
- const AtomVector<AbsoluteAtom> &absolute() const override {
+ const AtomRange<AbsoluteAtom> absolute() const override {
llvm_unreachable("internal error");
}
+ void clearAtoms() override {
+ }
+
private:
std::error_code _ec;
};
diff --git a/lld/include/lld/Core/Resolver.h b/lld/include/lld/Core/Resolver.h
index d7b42b6e26e..efaf19ff119 100644
--- a/lld/include/lld/Core/Resolver.h
+++ b/lld/include/lld/Core/Resolver.h
@@ -35,10 +35,10 @@ public:
Resolver(LinkingContext &ctx) : _ctx(ctx), _result(new MergedFile()) {}
// InputFiles::Handler methods
- void doDefinedAtom(const DefinedAtom&);
- bool doUndefinedAtom(const UndefinedAtom &);
- void doSharedLibraryAtom(const SharedLibraryAtom &);
- void doAbsoluteAtom(const AbsoluteAtom &);
+ void doDefinedAtom(OwningAtomPtr<DefinedAtom> atom);
+ bool doUndefinedAtom(OwningAtomPtr<UndefinedAtom> atom);
+ void doSharedLibraryAtom(OwningAtomPtr<SharedLibraryAtom> atom);
+ void doAbsoluteAtom(OwningAtomPtr<AbsoluteAtom> atom);
// Handle files, this adds atoms from the current file thats
// being processed by the resolver
@@ -71,17 +71,16 @@ private:
UndefCallback callback);
void markLive(const Atom *atom);
- void addAtoms(const std::vector<const DefinedAtom *>&);
class MergedFile : public SimpleFile {
public:
MergedFile() : SimpleFile("<linker-internal>", kindResolverMergedObject) {}
- void addAtoms(std::vector<const Atom*>& atoms);
+ void addAtoms(llvm::MutableArrayRef<OwningAtomPtr<Atom>> atoms);
};
LinkingContext &_ctx;
SymbolTable _symbolTable;
- std::vector<const Atom *> _atoms;
+ std::vector<OwningAtomPtr<Atom>> _atoms;
std::set<const Atom *> _deadStripRoots;
llvm::DenseSet<const Atom *> _liveAtoms;
llvm::DenseSet<const Atom *> _deadAtoms;
diff --git a/lld/include/lld/Core/SharedLibraryAtom.h b/lld/include/lld/Core/SharedLibraryAtom.h
index 0f4648fa357..7fec7a3e3d2 100644
--- a/lld/include/lld/Core/SharedLibraryAtom.h
+++ b/lld/include/lld/Core/SharedLibraryAtom.h
@@ -44,6 +44,8 @@ public:
protected:
SharedLibraryAtom() : Atom(definitionSharedLibrary) {}
+
+ ~SharedLibraryAtom() override = default;
};
} // namespace lld
diff --git a/lld/include/lld/Core/SharedLibraryFile.h b/lld/include/lld/Core/SharedLibraryFile.h
index 2e4771f614e..5fa0e9574f0 100644
--- a/lld/include/lld/Core/SharedLibraryFile.h
+++ b/lld/include/lld/Core/SharedLibraryFile.h
@@ -27,28 +27,35 @@ public:
/// Check if the shared library exports a symbol with the specified name.
/// If so, return a SharedLibraryAtom which represents that exported
/// symbol. Otherwise return nullptr.
- virtual const SharedLibraryAtom *exports(StringRef name,
+ virtual OwningAtomPtr<SharedLibraryAtom> exports(StringRef name,
bool dataSymbolOnly) const = 0;
// Returns the install name.
virtual StringRef getDSOName() const = 0;
- const AtomVector<DefinedAtom> &defined() const override {
+ const AtomRange<DefinedAtom> defined() const override {
return _definedAtoms;
}
- const AtomVector<UndefinedAtom> &undefined() const override {
+ const AtomRange<UndefinedAtom> undefined() const override {
return _undefinedAtoms;
}
- const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+ const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
return _sharedLibraryAtoms;
}
- const AtomVector<AbsoluteAtom> &absolute() const override {
+ const AtomRange<AbsoluteAtom> absolute() const override {
return _absoluteAtoms;
}
+ void clearAtoms() override {
+ _definedAtoms.clear();
+ _undefinedAtoms.clear();
+ _sharedLibraryAtoms.clear();
+ _absoluteAtoms.clear();
+ }
+
protected:
/// only subclasses of SharedLibraryFile can be instantiated
explicit SharedLibraryFile(StringRef path) : File(path, kindSharedLibrary) {}
diff --git a/lld/include/lld/Core/Simple.h b/lld/include/lld/Core/Simple.h
index a06eecd9be1..f010387d5bd 100644
--- a/lld/include/lld/Core/Simple.h
+++ b/lld/include/lld/Core/Simple.h
@@ -31,20 +31,35 @@ public:
SimpleFile(StringRef path, File::Kind kind)
: File(path, kind) {}
- void addAtom(const DefinedAtom &a) { _defined.push_back(&a); }
- void addAtom(const UndefinedAtom &a) { _undefined.push_back(&a); }
- void addAtom(const SharedLibraryAtom &a) { _shared.push_back(&a); }
- void addAtom(const AbsoluteAtom &a) { _absolute.push_back(&a); }
+ ~SimpleFile() override {
+ _defined.clear();
+ _undefined.clear();
+ _shared.clear();
+ _absolute.clear();
+ }
+
+ void addAtom(DefinedAtom &a) {
+ _defined.push_back(OwningAtomPtr<DefinedAtom>(&a));
+ }
+ void addAtom(UndefinedAtom &a) {
+ _undefined.push_back(OwningAtomPtr<UndefinedAtom>(&a));
+ }
+ void addAtom(SharedLibraryAtom &a) {
+ _shared.push_back(OwningAtomPtr<SharedLibraryAtom>(&a));
+ }
+ void addAtom(AbsoluteAtom &a) {
+ _absolute.push_back(OwningAtomPtr<AbsoluteAtom>(&a));
+ }
void addAtom(const Atom &atom) {
if (auto *p = dyn_cast<DefinedAtom>(&atom)) {
- _defined.push_back(p);
+ addAtom(const_cast<DefinedAtom &>(*p));
} else if (auto *p = dyn_cast<UndefinedAtom>(&atom)) {
- _undefined.push_back(p);
+ addAtom(const_cast<UndefinedAtom &>(*p));
} else if (auto *p = dyn_cast<SharedLibraryAtom>(&atom)) {
- _shared.push_back(p);
+ addAtom(const_cast<SharedLibraryAtom &>(*p));
} else if (auto *p = dyn_cast<AbsoluteAtom>(&atom)) {
- _absolute.push_back(p);
+ addAtom(const_cast<AbsoluteAtom &>(*p));
} else {
llvm_unreachable("atom has unknown definition kind");
}
@@ -52,25 +67,35 @@ public:
void removeDefinedAtomsIf(std::function<bool(const DefinedAtom *)> pred) {
auto &atoms = _defined;
- auto newEnd = std::remove_if(atoms.begin(), atoms.end(), pred);
+ auto newEnd = std::remove_if(atoms.begin(), atoms.end(),
+ [&pred](OwningAtomPtr<DefinedAtom> &p) {
+ return pred(p.get());
+ });
atoms.erase(newEnd, atoms.end());
}
- const AtomVector<DefinedAtom> &defined() const override { return _defined; }
+ const AtomRange<DefinedAtom> defined() const override { return _defined; }
- const AtomVector<UndefinedAtom> &undefined() const override {
+ const AtomRange<UndefinedAtom> undefined() const override {
return _undefined;
}
- const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+ const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
return _shared;
}
- const AtomVector<AbsoluteAtom> &absolute() const override {
+ const AtomRange<AbsoluteAtom> absolute() const override {
return _absolute;
}
- typedef llvm::MutableArrayRef<const DefinedAtom *> DefinedAtomRange;
+ void clearAtoms() override {
+ _defined.clear();
+ _undefined.clear();
+ _shared.clear();
+ _absolute.clear();
+ }
+
+ typedef AtomRange<DefinedAtom> DefinedAtomRange;
DefinedAtomRange definedAtoms() { return _defined; }
private:
@@ -169,6 +194,10 @@ public:
_references.setAllocator(&f.allocator());
}
+ ~SimpleDefinedAtom() {
+ _references.clearAndLeakNodesUnsafely();
+ }
+
const File &file() const override { return _file; }
StringRef name() const override { return StringRef(); }
@@ -265,6 +294,8 @@ public:
assert(!name.empty() && "UndefinedAtoms must have a name");
}
+ ~SimpleUndefinedAtom() override = default;
+
/// file - returns the File that produced/owns this Atom
const File &file() const override { return _file; }
diff --git a/lld/include/lld/Core/UndefinedAtom.h b/lld/include/lld/Core/UndefinedAtom.h
index 3e58f800ea1..f45d6ecda6b 100644
--- a/lld/include/lld/Core/UndefinedAtom.h
+++ b/lld/include/lld/Core/UndefinedAtom.h
@@ -59,6 +59,8 @@ public:
protected:
UndefinedAtom() : Atom(definitionUndefined) {}
+
+ ~UndefinedAtom() override = default;
};
} // namespace lld
OpenPOWER on IntegriCloud