summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/include/lld/Core/Atom.h47
-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
-rw-r--r--lld/lib/Core/File.cpp2
-rw-r--r--lld/lib/Core/Resolver.cpp141
-rw-r--r--lld/lib/Driver/DarwinLdDriver.cpp9
-rw-r--r--lld/lib/ReaderWriter/FileArchive.cpp15
-rw-r--r--lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp4
-rw-r--r--lld/lib/ReaderWriter/MachO/Atoms.h6
-rw-r--r--lld/lib/ReaderWriter/MachO/CompactUnwindPass.cpp2
-rw-r--r--lld/lib/ReaderWriter/MachO/ExecutableAtoms.h15
-rw-r--r--lld/lib/ReaderWriter/MachO/File.h26
-rw-r--r--lld/lib/ReaderWriter/MachO/FlatNamespaceFile.h27
-rw-r--r--lld/lib/ReaderWriter/MachO/GOTPass.cpp2
-rw-r--r--lld/lib/ReaderWriter/MachO/LayoutPass.cpp28
-rw-r--r--lld/lib/ReaderWriter/MachO/LayoutPass.h14
-rw-r--r--lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp14
-rw-r--r--lld/lib/ReaderWriter/MachO/ObjCPass.cpp2
-rw-r--r--lld/lib/ReaderWriter/MachO/SectCreateFile.h17
-rw-r--r--lld/lib/ReaderWriter/MachO/StubsPass.cpp10
-rw-r--r--lld/lib/ReaderWriter/MachO/TLVPass.cpp2
-rw-r--r--lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp142
27 files changed, 516 insertions, 203 deletions
diff --git a/lld/include/lld/Core/Atom.h b/lld/include/lld/Core/Atom.h
index 27fdde022ba..6a4308918c2 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,49 @@ 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)
+ 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
diff --git a/lld/lib/Core/File.cpp b/lld/lib/Core/File.cpp
index ac95f101679..b84132bfecd 100644
--- a/lld/lib/Core/File.cpp
+++ b/lld/lib/Core/File.cpp
@@ -13,7 +13,7 @@
namespace lld {
-File::~File() {}
+File::~File() { }
File::AtomVector<DefinedAtom> File::_noDefinedAtoms;
File::AtomVector<UndefinedAtom> File::_noUndefinedAtoms;
diff --git a/lld/lib/Core/Resolver.cpp b/lld/lib/Core/Resolver.cpp
index b8964358c0e..d94699a9f13 100644
--- a/lld/lib/Core/Resolver.cpp
+++ b/lld/lib/Core/Resolver.cpp
@@ -33,16 +33,16 @@ ErrorOr<bool> Resolver::handleFile(File &file) {
if (auto ec = _ctx.handleLoadedFile(file))
return ec;
bool undefAdded = false;
- for (const DefinedAtom *atom : file.defined())
- doDefinedAtom(*atom);
- for (const UndefinedAtom *atom : file.undefined()) {
- if (doUndefinedAtom(*atom))
+ for (auto &atom : file.defined().owning_ptrs())
+ doDefinedAtom(std::move(atom));
+ for (auto &atom : file.undefined().owning_ptrs()) {
+ if (doUndefinedAtom(std::move(atom)))
undefAdded = true;
}
- for (const SharedLibraryAtom *atom : file.sharedLibrary())
- doSharedLibraryAtom(*atom);
- for (const AbsoluteAtom *atom : file.absolute())
- doAbsoluteAtom(*atom);
+ for (auto &atom : file.sharedLibrary().owning_ptrs())
+ doSharedLibraryAtom(std::move(atom));
+ for (auto &atom : file.absolute().owning_ptrs())
+ doAbsoluteAtom(std::move(atom));
return undefAdded;
}
@@ -113,9 +113,9 @@ std::error_code Resolver::handleSharedLibrary(File &file) {
undefAddedOrError = forEachUndefines(file, searchForOverrides,
[&](StringRef undefName,
bool dataSymbolOnly)->ErrorOr<bool> {
- if (const SharedLibraryAtom *atom =
- sharedLibrary->exports(undefName, dataSymbolOnly))
- doSharedLibraryAtom(*atom);
+ auto atom = sharedLibrary->exports(undefName, dataSymbolOnly);
+ if (atom.get())
+ doSharedLibraryAtom(std::move(atom));
return false;
});
@@ -124,84 +124,79 @@ std::error_code Resolver::handleSharedLibrary(File &file) {
return std::error_code();
}
-bool Resolver::doUndefinedAtom(const UndefinedAtom &atom) {
+bool Resolver::doUndefinedAtom(OwningAtomPtr<UndefinedAtom> atom) {
DEBUG_WITH_TYPE("resolver", llvm::dbgs()
<< " UndefinedAtom: "
- << llvm::format("0x%09lX", &atom)
- << ", name=" << atom.name() << "\n");
-
- // add to list of known atoms
- _atoms.push_back(&atom);
+ << llvm::format("0x%09lX", atom.get())
+ << ", name=" << atom.get()->name() << "\n");
// tell symbol table
- bool newUndefAdded = _symbolTable.add(atom);
+ bool newUndefAdded = _symbolTable.add(*atom.get());
if (newUndefAdded)
- _undefines.push_back(atom.name());
+ _undefines.push_back(atom.get()->name());
+
+ // add to list of known atoms
+ _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
return newUndefAdded;
}
// Called on each atom when a file is added. Returns true if a given
// atom is added to the symbol table.
-void Resolver::doDefinedAtom(const DefinedAtom &atom) {
+void Resolver::doDefinedAtom(OwningAtomPtr<DefinedAtom> atom) {
DEBUG_WITH_TYPE("resolver", llvm::dbgs()
<< " DefinedAtom: "
- << llvm::format("0x%09lX", &atom)
+ << llvm::format("0x%09lX", atom.get())
<< ", file=#"
- << atom.file().ordinal()
+ << atom.get()->file().ordinal()
<< ", atom=#"
- << atom.ordinal()
+ << atom.get()->ordinal()
<< ", name="
- << atom.name()
+ << atom.get()->name()
<< ", type="
- << atom.contentType()
+ << atom.get()->contentType()
<< "\n");
- // add to list of known atoms
- _atoms.push_back(&atom);
- _symbolTable.add(atom);
-
// An atom that should never be dead-stripped is a dead-strip root.
- if (_ctx.deadStrip() && atom.deadStrip() == DefinedAtom::deadStripNever) {
- _deadStripRoots.insert(&atom);
+ if (_ctx.deadStrip() &&
+ atom.get()->deadStrip() == DefinedAtom::deadStripNever) {
+ _deadStripRoots.insert(atom.get());
}
+
+ // add to list of known atoms
+ _symbolTable.add(*atom.get());
+ _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
}
-void Resolver::doSharedLibraryAtom(const SharedLibraryAtom &atom) {
+void Resolver::doSharedLibraryAtom(OwningAtomPtr<SharedLibraryAtom> atom) {
DEBUG_WITH_TYPE("resolver", llvm::dbgs()
<< " SharedLibraryAtom: "
- << llvm::format("0x%09lX", &atom)
+ << llvm::format("0x%09lX", atom.get())
<< ", name="
- << atom.name()
+ << atom.get()->name()
<< "\n");
- // add to list of known atoms
- _atoms.push_back(&atom);
-
// tell symbol table
- _symbolTable.add(atom);
+ _symbolTable.add(*atom.get());
+
+ // add to list of known atoms
+ _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
}
-void Resolver::doAbsoluteAtom(const AbsoluteAtom &atom) {
+void Resolver::doAbsoluteAtom(OwningAtomPtr<AbsoluteAtom> atom) {
DEBUG_WITH_TYPE("resolver", llvm::dbgs()
<< " AbsoluteAtom: "
- << llvm::format("0x%09lX", &atom)
+ << llvm::format("0x%09lX", atom.get())
<< ", name="
- << atom.name()
+ << atom.get()->name()
<< "\n");
- // add to list of known atoms
- _atoms.push_back(&atom);
-
// tell symbol table
- if (atom.scope() != Atom::scopeTranslationUnit)
- _symbolTable.add(atom);
-}
+ if (atom.get()->scope() != Atom::scopeTranslationUnit)
+ _symbolTable.add(*atom.get());
-// utility to add a vector of atoms
-void Resolver::addAtoms(const std::vector<const DefinedAtom *> &newAtoms) {
- for (const DefinedAtom *newAtom : newAtoms)
- doDefinedAtom(*newAtom);
+ // add to list of known atoms
+ _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
}
// Returns true if at least one of N previous files has created an
@@ -316,8 +311,8 @@ void Resolver::updateReferences() {
DEBUG_WITH_TYPE("resolver",
llvm::dbgs() << "******** Updating references:\n");
ScopedTask task(getDefaultDomain(), "updateReferences");
- for (const Atom *atom : _atoms) {
- if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom)) {
+ for (const OwningAtomPtr<Atom> &atom : _atoms) {
+ if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom.get())) {
for (const Reference *ref : *defAtom) {
// A reference of type kindAssociate should't be updated.
// Instead, an atom having such reference will be removed
@@ -325,7 +320,7 @@ void Resolver::updateReferences() {
// go away as a group.
if (ref->kindNamespace() == lld::Reference::KindNamespace::all &&
ref->kindValue() == lld::Reference::kindAssociate) {
- if (_symbolTable.isCoalescedAway(atom))
+ if (_symbolTable.isCoalescedAway(atom.get()))
_deadAtoms.insert(ref->target());
continue;
}
@@ -373,19 +368,19 @@ void Resolver::deadStripOptimize() {
// Make a reverse map of such references before traversing the graph.
// While traversing the list of atoms, mark AbsoluteAtoms as live
// in order to avoid reclaim.
- for (const Atom *atom : _atoms) {
- if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom))
+ for (const OwningAtomPtr<Atom> &atom : _atoms) {
+ if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom.get()))
for (const Reference *ref : *defAtom)
if (isBackref(ref))
- _reverseRef.insert(std::make_pair(ref->target(), atom));
- if (const AbsoluteAtom *absAtom = dyn_cast<AbsoluteAtom>(atom))
+ _reverseRef.insert(std::make_pair(ref->target(), atom.get()));
+ if (const AbsoluteAtom *absAtom = dyn_cast<AbsoluteAtom>(atom.get()))
markLive(absAtom);
}
// By default, shared libraries are built with all globals as dead strip roots
if (_ctx.globalsAreDeadStripRoots())
- for (const Atom *atom : _atoms)
- if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom))
+ for (const OwningAtomPtr<Atom> &atom : _atoms)
+ if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom.get()))
if (defAtom->scope() == DefinedAtom::scopeGlobal)
_deadStripRoots.insert(defAtom);
@@ -401,8 +396,9 @@ void Resolver::deadStripOptimize() {
markLive(dsrAtom);
// now remove all non-live atoms from _atoms
- _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(), [&](const Atom *a) {
- return _liveAtoms.count(a) == 0;
+ _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(),
+ [&](OwningAtomPtr<Atom> &a) {
+ return _liveAtoms.count(a.get()) == 0;
}),
_atoms.end());
}
@@ -461,8 +457,10 @@ void Resolver::removeCoalescedAwayAtoms() {
DEBUG_WITH_TYPE("resolver",
llvm::dbgs() << "******** Removing coalesced away atoms:\n");
ScopedTask task(getDefaultDomain(), "removeCoalescedAwayAtoms");
- _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(), [&](const Atom *a) {
- return _symbolTable.isCoalescedAway(a) || _deadAtoms.count(a);
+ _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(),
+ [&](OwningAtomPtr<Atom> &a) {
+ return _symbolTable.isCoalescedAway(a.get()) ||
+ _deadAtoms.count(a.get());
}),
_atoms.end());
}
@@ -488,15 +486,16 @@ bool Resolver::resolve() {
return true;
}
-void Resolver::MergedFile::addAtoms(std::vector<const Atom *> &all) {
+void Resolver::MergedFile::addAtoms(
+ llvm::MutableArrayRef<OwningAtomPtr<Atom>> all) {
ScopedTask task(getDefaultDomain(), "addAtoms");
DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "Resolver final atom list:\n");
- for (const Atom *atom : all) {
+ for (OwningAtomPtr<Atom> &atom : all) {
#ifndef NDEBUG
- if (auto *definedAtom = dyn_cast<DefinedAtom>(atom)) {
+ if (auto *definedAtom = dyn_cast<DefinedAtom>(atom.get())) {
DEBUG_WITH_TYPE("resolver", llvm::dbgs()
- << llvm::format(" 0x%09lX", atom)
+ << llvm::format(" 0x%09lX", definedAtom)
<< ", file=#"
<< definedAtom->file().ordinal()
<< ", atom=#"
@@ -508,13 +507,13 @@ void Resolver::MergedFile::addAtoms(std::vector<const Atom *> &all) {
<< "\n");
} else {
DEBUG_WITH_TYPE("resolver", llvm::dbgs()
- << llvm::format(" 0x%09lX", atom)
+ << llvm::format(" 0x%09lX", atom.get())
<< ", name="
- << atom->name()
+ << atom.get()->name()
<< "\n");
}
#endif
- addAtom(*atom);
+ addAtom(*atom.release());
}
}
diff --git a/lld/lib/Driver/DarwinLdDriver.cpp b/lld/lib/Driver/DarwinLdDriver.cpp
index 4a859f3d605..914c23642ac 100644
--- a/lld/lib/Driver/DarwinLdDriver.cpp
+++ b/lld/lib/Driver/DarwinLdDriver.cpp
@@ -1169,7 +1169,14 @@ bool link(llvm::ArrayRef<const char *> args, raw_ostream &diagnostics) {
Resolver resolver(ctx);
if (!resolver.resolve())
return false;
- std::unique_ptr<SimpleFile> merged = resolver.resultFile();
+ SimpleFile *merged = nullptr;
+ {
+ std::unique_ptr<SimpleFile> mergedFile = resolver.resultFile();
+ merged = mergedFile.get();
+ auto &members = ctx.getNodes();
+ members.insert(members.begin(),
+ llvm::make_unique<FileNode>(std::move(mergedFile)));
+ }
resolveTask.end();
// Run passes on linked atoms.
diff --git a/lld/lib/ReaderWriter/FileArchive.cpp b/lld/lib/ReaderWriter/FileArchive.cpp
index a47024ca4f6..73b86127797 100644
--- a/lld/lib/ReaderWriter/FileArchive.cpp
+++ b/lld/lib/ReaderWriter/FileArchive.cpp
@@ -88,22 +88,29 @@ public:
return std::error_code();
}
- const AtomVector<DefinedAtom> &defined() const override {
+ const AtomRange<DefinedAtom> defined() const override {
return _noDefinedAtoms;
}
- const AtomVector<UndefinedAtom> &undefined() const override {
+ const AtomRange<UndefinedAtom> undefined() const override {
return _noUndefinedAtoms;
}
- const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+ const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
return _noSharedLibraryAtoms;
}
- const AtomVector<AbsoluteAtom> &absolute() const override {
+ const AtomRange<AbsoluteAtom> absolute() const override {
return _noAbsoluteAtoms;
}
+ void clearAtoms() override {
+ _noDefinedAtoms.clear();
+ _noUndefinedAtoms.clear();
+ _noSharedLibraryAtoms.clear();
+ _noAbsoluteAtoms.clear();
+ }
+
protected:
std::error_code doParse() override {
// Make Archive object which will be owned by FileArchive object.
diff --git a/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp b/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
index cefa745add9..7eda42ef7a0 100644
--- a/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
+++ b/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
@@ -1429,6 +1429,8 @@ public:
_name = tmp.copy(file.allocator());
}
+ ~Thumb2ToArmShimAtom() override = default;
+
StringRef name() const override {
return _name;
}
@@ -1472,6 +1474,8 @@ public:
_name = tmp.copy(file.allocator());
}
+ ~ArmToThumbShimAtom() override = default;
+
StringRef name() const override {
return _name;
}
diff --git a/lld/lib/ReaderWriter/MachO/Atoms.h b/lld/lib/ReaderWriter/MachO/Atoms.h
index f50a6cffe18..c3117d4ac89 100644
--- a/lld/lib/ReaderWriter/MachO/Atoms.h
+++ b/lld/lib/ReaderWriter/MachO/Atoms.h
@@ -32,6 +32,8 @@ public:
_contentType(type), _scope(scope), _merge(mergeNo), _thumb(false),
_noDeadStrip(noDeadStrip) {}
+ ~MachODefinedAtom() override = default;
+
uint64_t size() const override { return _content.size(); }
ContentType contentType() const override { return _contentType; }
@@ -83,6 +85,8 @@ public:
content, align),
_sectionName(sectionName) {}
+ ~MachODefinedCustomSectionAtom() override = default;
+
SectionChoice sectionChoice() const override {
return DefinedAtom::sectionCustomRequired;
}
@@ -101,6 +105,8 @@ public:
: SimpleDefinedAtom(f), _name(name), _scope(scope), _size(size),
_align(align) {}
+ ~MachOTentativeDefAtom() override = default;
+
uint64_t size() const override { return _size; }
Merge merge() const override { return DefinedAtom::mergeAsTentative; }
diff --git a/lld/lib/ReaderWriter/MachO/CompactUnwindPass.cpp b/lld/lib/ReaderWriter/MachO/CompactUnwindPass.cpp
index d2793033b5f..088f93bf630 100644
--- a/lld/lib/ReaderWriter/MachO/CompactUnwindPass.cpp
+++ b/lld/lib/ReaderWriter/MachO/CompactUnwindPass.cpp
@@ -88,6 +88,8 @@ public:
addSecondLevelPages(pages);
}
+ ~UnwindInfoAtom() override = default;
+
ContentType contentType() const override {
return DefinedAtom::typeProcessedUnwindInfo;
}
diff --git a/lld/lib/ReaderWriter/MachO/ExecutableAtoms.h b/lld/lib/ReaderWriter/MachO/ExecutableAtoms.h
index e1a252bbf9b..acced33b7e7 100644
--- a/lld/lib/ReaderWriter/MachO/ExecutableAtoms.h
+++ b/lld/lib/ReaderWriter/MachO/ExecutableAtoms.h
@@ -122,21 +122,28 @@ public:
ArrayRef<uint8_t>(), DefinedAtom::Alignment(1)));
}
- 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 _noUndefinedAtoms;
}
- const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+ const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
return _noSharedLibraryAtoms;
}
- const AtomVector<AbsoluteAtom> &absolute() const override {
+ const AtomRange<AbsoluteAtom> absolute() const override {
return _noAbsoluteAtoms;
}
+ void clearAtoms() override {
+ _definedAtoms.clear();
+ _noUndefinedAtoms.clear();
+ _noSharedLibraryAtoms.clear();
+ _noAbsoluteAtoms.clear();
+ }
+
private:
mutable AtomVector<DefinedAtom> _definedAtoms;
diff --git a/lld/lib/ReaderWriter/MachO/File.h b/lld/lib/ReaderWriter/MachO/File.h
index a0d20ea540f..f7262bbfaef 100644
--- a/lld/lib/ReaderWriter/MachO/File.h
+++ b/lld/lib/ReaderWriter/MachO/File.h
@@ -275,7 +275,8 @@ public:
MachODylibFile(StringRef path) : SharedLibraryFile(path) {}
- const SharedLibraryAtom *exports(StringRef name, bool isData) const override {
+ OwningAtomPtr<SharedLibraryAtom> exports(StringRef name,
+ bool isData) const override {
// Pass down _installName so that if this requested symbol
// is re-exported through this dylib, the SharedLibraryAtom's loadName()
// is this dylib installName and not the implementation dylib's.
@@ -328,25 +329,30 @@ public:
}
private:
- const SharedLibraryAtom *exports(StringRef name,
+ OwningAtomPtr<SharedLibraryAtom> exports(StringRef name,
StringRef installName) const {
// First, check if requested symbol is directly implemented by this dylib.
auto entry = _nameToAtom.find(name);
if (entry != _nameToAtom.end()) {
- if (!entry->second.atom) {
- // Lazily create SharedLibraryAtom.
- entry->second.atom =
- new (allocator()) MachOSharedLibraryAtom(*this, name, installName,
- entry->second.weakDef);
- }
- return entry->second.atom;
+ // FIXME: Make this map a set and only used in assert builds.
+ // Note, its safe to assert here as the resolver is the only client of
+ // this API and it only requests exports for undefined symbols.
+ // If we return from here we are no longer undefined so we should never
+ // get here again.
+ assert(!entry->second.atom && "Duplicate shared library export");
+ bool weakDef = entry->second.weakDef;
+ auto *atom = new (allocator()) MachOSharedLibraryAtom(*this, name,
+ installName,
+ weakDef);
+ entry->second.atom = atom;
+ return atom;
}
// Next, check if symbol is implemented in some re-exported dylib.
for (const ReExportedDylib &dylib : _reExportedDylibs) {
assert(dylib.file);
auto atom = dylib.file->exports(name, installName);
- if (atom)
+ if (atom.get())
return atom;
}
diff --git a/lld/lib/ReaderWriter/MachO/FlatNamespaceFile.h b/lld/lib/ReaderWriter/MachO/FlatNamespaceFile.h
index 6c6a9262ba2..08b28f43a15 100644
--- a/lld/lib/ReaderWriter/MachO/FlatNamespaceFile.h
+++ b/lld/lib/ReaderWriter/MachO/FlatNamespaceFile.h
@@ -25,34 +25,35 @@ public:
FlatNamespaceFile(const MachOLinkingContext &context)
: SharedLibraryFile("flat namespace") { }
- const SharedLibraryAtom *exports(StringRef name,
+ OwningAtomPtr<SharedLibraryAtom> exports(StringRef name,
bool dataSymbolOnly) const override {
- _sharedLibraryAtoms.push_back(
- new (allocator()) MachOSharedLibraryAtom(*this, name, getDSOName(),
- false));
-
- return _sharedLibraryAtoms.back();
+ return new (allocator()) MachOSharedLibraryAtom(*this, name, getDSOName(),
+ false);
}
StringRef getDSOName() const override { return "flat-namespace"; }
- const AtomVector<DefinedAtom> &defined() const override {
+ const AtomRange<DefinedAtom> defined() const override {
return _noDefinedAtoms;
}
- const AtomVector<UndefinedAtom> &undefined() const override {
+ const AtomRange<UndefinedAtom> undefined() const override {
return _noUndefinedAtoms;
}
- const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
- return _sharedLibraryAtoms;
+ const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
+ return _noSharedLibraryAtoms;
}
- const AtomVector<AbsoluteAtom> &absolute() const override {
+ const AtomRange<AbsoluteAtom> absolute() const override {
return _noAbsoluteAtoms;
}
-private:
- mutable AtomVector<SharedLibraryAtom> _sharedLibraryAtoms;
+ void clearAtoms() override {
+ _noDefinedAtoms.clear();
+ _noUndefinedAtoms.clear();
+ _noSharedLibraryAtoms.clear();
+ _noAbsoluteAtoms.clear();
+ }
};
} // namespace mach_o
diff --git a/lld/lib/ReaderWriter/MachO/GOTPass.cpp b/lld/lib/ReaderWriter/MachO/GOTPass.cpp
index eac48644f6b..400dbf7de9d 100644
--- a/lld/lib/ReaderWriter/MachO/GOTPass.cpp
+++ b/lld/lib/ReaderWriter/MachO/GOTPass.cpp
@@ -54,6 +54,8 @@ public:
GOTEntryAtom(const File &file, bool is64, StringRef name)
: SimpleDefinedAtom(file), _is64(is64), _name(name) { }
+ ~GOTEntryAtom() override = default;
+
ContentType contentType() const override {
return DefinedAtom::typeGOT;
}
diff --git a/lld/lib/ReaderWriter/MachO/LayoutPass.cpp b/lld/lib/ReaderWriter/MachO/LayoutPass.cpp
index 0c14ee9d39a..b22bc5482ca 100644
--- a/lld/lib/ReaderWriter/MachO/LayoutPass.cpp
+++ b/lld/lib/ReaderWriter/MachO/LayoutPass.cpp
@@ -146,7 +146,7 @@ static void printDefinedAtoms(const SimpleFile::DefinedAtomRange &atomRange) {
/// Verify that the followon chain is sane. Should not be called in
/// release binary.
-void LayoutPass::checkFollowonChain(SimpleFile::DefinedAtomRange &range) {
+void LayoutPass::checkFollowonChain(const SimpleFile::DefinedAtomRange &range) {
ScopedTask task(getDefaultDomain(), "LayoutPass::checkFollowonChain");
// Verify that there's no cycle in follow-on chain.
@@ -176,8 +176,8 @@ static bool compareAtomsSub(const LayoutPass::SortKey &lc,
const LayoutPass::SortKey &rc,
LayoutPass::SortOverride customSorter,
std::string &reason) {
- const DefinedAtom *left = lc._atom;
- const DefinedAtom *right = rc._atom;
+ const DefinedAtom *left = lc._atom.get();
+ const DefinedAtom *right = rc._atom.get();
if (left == right) {
reason = "same";
return false;
@@ -252,8 +252,9 @@ static bool compareAtoms(const LayoutPass::SortKey &lc,
bool result = compareAtomsSub(lc, rc, customSorter, reason);
DEBUG({
StringRef comp = result ? "<" : ">=";
- llvm::dbgs() << "Layout: '" << lc._atom->name() << "' " << comp << " '"
- << rc._atom->name() << "' (" << reason << ")\n";
+ llvm::dbgs() << "Layout: '" << lc._atom.get()->name()
+ << "' " << comp << " '"
+ << rc._atom.get()->name() << "' (" << reason << ")\n";
});
return result;
}
@@ -329,7 +330,7 @@ void LayoutPass::setChainRoot(const DefinedAtom *targetAtom,
/// d) If the targetAtom is part of a different chain and the root of the
/// targetAtom until the targetAtom has all atoms of size 0, then chain the
/// targetAtoms and its tree to the current chain
-void LayoutPass::buildFollowOnTable(SimpleFile::DefinedAtomRange &range) {
+void LayoutPass::buildFollowOnTable(const SimpleFile::DefinedAtomRange &range) {
ScopedTask task(getDefaultDomain(), "LayoutPass::buildFollowOnTable");
// Set the initial size of the followon and the followonNext hash to the
// number of atoms that we have.
@@ -397,7 +398,8 @@ void LayoutPass::buildFollowOnTable(SimpleFile::DefinedAtomRange &range) {
/// assigning ordinals to each atom, if the atoms have their ordinals
/// already assigned skip the atom and move to the next. This is the
/// main map thats used to sort the atoms while comparing two atoms together
-void LayoutPass::buildOrdinalOverrideMap(SimpleFile::DefinedAtomRange &range) {
+void
+LayoutPass::buildOrdinalOverrideMap(const SimpleFile::DefinedAtomRange &range) {
ScopedTask task(getDefaultDomain(), "LayoutPass::buildOrdinalOverrideMap");
uint64_t index = 0;
for (const DefinedAtom *ai : range) {
@@ -419,12 +421,12 @@ void LayoutPass::buildOrdinalOverrideMap(SimpleFile::DefinedAtomRange &range) {
std::vector<LayoutPass::SortKey>
LayoutPass::decorate(SimpleFile::DefinedAtomRange &atomRange) const {
std::vector<SortKey> ret;
- for (const DefinedAtom *atom : atomRange) {
- auto ri = _followOnRoots.find(atom);
- auto oi = _ordinalOverrideMap.find(atom);
- const DefinedAtom *root = (ri == _followOnRoots.end()) ? atom : ri->second;
+ for (OwningAtomPtr<DefinedAtom> &atom : atomRange.owning_ptrs()) {
+ auto ri = _followOnRoots.find(atom.get());
+ auto oi = _ordinalOverrideMap.find(atom.get());
+ const auto *root = (ri == _followOnRoots.end()) ? atom.get() : ri->second;
uint64_t override = (oi == _ordinalOverrideMap.end()) ? 0 : oi->second;
- ret.push_back(SortKey(atom, root, override));
+ ret.push_back(SortKey(std::move(atom), root, override));
}
return ret;
}
@@ -433,7 +435,7 @@ void LayoutPass::undecorate(SimpleFile::DefinedAtomRange &atomRange,
std::vector<SortKey> &keys) const {
size_t i = 0;
for (SortKey &k : keys)
- atomRange[i++] = k._atom;
+ atomRange[i++] = std::move(k._atom);
}
/// Perform the actual pass
diff --git a/lld/lib/ReaderWriter/MachO/LayoutPass.h b/lld/lib/ReaderWriter/MachO/LayoutPass.h
index d6072b0ca4f..d254891a789 100644
--- a/lld/lib/ReaderWriter/MachO/LayoutPass.h
+++ b/lld/lib/ReaderWriter/MachO/LayoutPass.h
@@ -33,9 +33,10 @@ namespace mach_o {
class LayoutPass : public Pass {
public:
struct SortKey {
- SortKey(const DefinedAtom *atom, const DefinedAtom *root, uint64_t override)
- : _atom(atom), _root(root), _override(override) {}
- const DefinedAtom *_atom;
+ SortKey(OwningAtomPtr<DefinedAtom> &&atom,
+ const DefinedAtom *root, uint64_t override)
+ : _atom(std::move(atom)), _root(root), _override(override) {}
+ OwningAtomPtr<DefinedAtom> _atom;
const DefinedAtom *_root;
uint64_t _override;
};
@@ -53,10 +54,10 @@ public:
private:
// Build the followOn atoms chain as specified by the kindLayoutAfter
// reference type
- void buildFollowOnTable(SimpleFile::DefinedAtomRange &range);
+ void buildFollowOnTable(const SimpleFile::DefinedAtomRange &range);
// Build a map of Atoms to ordinals for sorting the atoms
- void buildOrdinalOverrideMap(SimpleFile::DefinedAtomRange &range);
+ void buildOrdinalOverrideMap(const SimpleFile::DefinedAtomRange &range);
const Registry &_registry;
SortOverride _customSorter;
@@ -85,11 +86,12 @@ private:
void setChainRoot(const DefinedAtom *targetAtom, const DefinedAtom *root);
std::vector<SortKey> decorate(SimpleFile::DefinedAtomRange &atomRange) const;
+
void undecorate(SimpleFile::DefinedAtomRange &atomRange,
std::vector<SortKey> &keys) const;
// Check if the follow-on graph is a correct structure. For debugging only.
- void checkFollowonChain(SimpleFile::DefinedAtomRange &range);
+ void checkFollowonChain(const SimpleFile::DefinedAtomRange &range);
};
} // namespace mach_o
diff --git a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
index 1cc87f0fac4..4431f347b27 100644
--- a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
@@ -171,7 +171,19 @@ bool MachOLinkingContext::sliceFromFatFile(MemoryBufferRef mb, uint32_t &offset,
MachOLinkingContext::MachOLinkingContext() {}
-MachOLinkingContext::~MachOLinkingContext() {}
+MachOLinkingContext::~MachOLinkingContext() {
+ // Atoms are allocated on BumpPtrAllocator's on File's.
+ // As we transfer atoms from one file to another, we need to clear all of the
+ // atoms before we remove any of the BumpPtrAllocator's.
+ auto &nodes = getNodes();
+ for (unsigned i = 0, e = nodes.size(); i != e; ++i) {
+ FileNode *node = dyn_cast<FileNode>(nodes[i].get());
+ if (!node)
+ continue;
+ File *file = node->getFile();
+ file->clearAtoms();
+ }
+}
void MachOLinkingContext::configure(HeaderFileType type, Arch arch, OS os,
uint32_t minOSVersion,
diff --git a/lld/lib/ReaderWriter/MachO/ObjCPass.cpp b/lld/lib/ReaderWriter/MachO/ObjCPass.cpp
index 13fa9888cec..f8c7310d4ae 100644
--- a/lld/lib/ReaderWriter/MachO/ObjCPass.cpp
+++ b/lld/lib/ReaderWriter/MachO/ObjCPass.cpp
@@ -56,6 +56,8 @@ public:
Data.info.flags |= (swiftVersion << 8);
}
+ ~ObjCImageInfoAtom() override = default;
+
ContentType contentType() const override {
return DefinedAtom::typeObjCImageInfo;
}
diff --git a/lld/lib/ReaderWriter/MachO/SectCreateFile.h b/lld/lib/ReaderWriter/MachO/SectCreateFile.h
index 5236071e0e0..49e65f63151 100644
--- a/lld/lib/ReaderWriter/MachO/SectCreateFile.h
+++ b/lld/lib/ReaderWriter/MachO/SectCreateFile.h
@@ -31,6 +31,8 @@ public:
_combinedName((segName + "/" + sectName).str()),
_content(std::move(content)) {}
+ ~SectCreateAtom() override = default;
+
uint64_t size() const override { return _content->getBufferSize(); }
Scope scope() const override { return scopeGlobal; }
@@ -67,22 +69,29 @@ public:
new (allocator()) SectCreateAtom(*this, seg, sect, std::move(content)));
}
- 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 _noUndefinedAtoms;
}
- const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+ const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
return _noSharedLibraryAtoms;
}
- const AtomVector<AbsoluteAtom> &absolute() const override {
+ const AtomRange<AbsoluteAtom> absolute() const override {
return _noAbsoluteAtoms;
}
+ void clearAtoms() override {
+ _definedAtoms.clear();
+ _noUndefinedAtoms.clear();
+ _noSharedLibraryAtoms.clear();
+ _noAbsoluteAtoms.clear();
+ }
+
private:
AtomVector<DefinedAtom> _definedAtoms;
};
diff --git a/lld/lib/ReaderWriter/MachO/StubsPass.cpp b/lld/lib/ReaderWriter/MachO/StubsPass.cpp
index e69d6698cb6..2539c26c4ea 100644
--- a/lld/lib/ReaderWriter/MachO/StubsPass.cpp
+++ b/lld/lib/ReaderWriter/MachO/StubsPass.cpp
@@ -37,6 +37,8 @@ public:
LazyPointerAtom(const File &file, bool is64)
: SimpleDefinedAtom(file), _is64(is64) { }
+ ~LazyPointerAtom() override = default;
+
ContentType contentType() const override {
return DefinedAtom::typeLazyPointer;
}
@@ -71,6 +73,8 @@ public:
NonLazyPointerAtom(const File &file, bool is64, ContentType contentType)
: SimpleDefinedAtom(file), _is64(is64), _contentType(contentType) { }
+ ~NonLazyPointerAtom() override = default;
+
ContentType contentType() const override {
return _contentType;
}
@@ -106,6 +110,8 @@ public:
StubAtom(const File &file, const ArchHandler::StubInfo &stubInfo)
: SimpleDefinedAtom(file), _stubInfo(stubInfo){ }
+ ~StubAtom() override = default;
+
ContentType contentType() const override {
return DefinedAtom::typeStub;
}
@@ -138,6 +144,8 @@ public:
StubHelperAtom(const File &file, const ArchHandler::StubInfo &stubInfo)
: SimpleDefinedAtom(file), _stubInfo(stubInfo) { }
+ ~StubHelperAtom() override = default;
+
ContentType contentType() const override {
return DefinedAtom::typeStubHelper;
}
@@ -171,6 +179,8 @@ public:
StubHelperCommonAtom(const File &file, const ArchHandler::StubInfo &stubInfo)
: SimpleDefinedAtom(file), _stubInfo(stubInfo) { }
+ ~StubHelperCommonAtom() override = default;
+
ContentType contentType() const override {
return DefinedAtom::typeStubHelper;
}
diff --git a/lld/lib/ReaderWriter/MachO/TLVPass.cpp b/lld/lib/ReaderWriter/MachO/TLVPass.cpp
index b12f006d7a1..41aa223d3c5 100644
--- a/lld/lib/ReaderWriter/MachO/TLVPass.cpp
+++ b/lld/lib/ReaderWriter/MachO/TLVPass.cpp
@@ -30,6 +30,8 @@ public:
TLVPEntryAtom(const File &file, bool is64, StringRef name)
: SimpleDefinedAtom(file), _is64(is64), _name(name) {}
+ ~TLVPEntryAtom() override = default;
+
ContentType contentType() const override {
return DefinedAtom::typeTLVInitializerPtr;
}
diff --git a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
index 091da9ca82b..bec2c68af31 100644
--- a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
+++ b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
@@ -195,7 +195,7 @@ private:
/// Mapping of Atoms.
template <typename T> class AtomList {
- typedef lld::File::AtomVector<T> Ty;
+ using Ty = std::vector<OwningAtomPtr<T>>;
public:
typename Ty::iterator begin() { return _atoms.begin(); }
@@ -503,10 +503,20 @@ template <> struct MappingTraits<ArchMember> {
// Declare that an AtomList is a yaml sequence.
template <typename T> struct SequenceTraits<AtomList<T> > {
static size_t size(IO &io, AtomList<T> &seq) { return seq._atoms.size(); }
- static const T *&element(IO &io, AtomList<T> &seq, size_t index) {
+ static T *&element(IO &io, AtomList<T> &seq, size_t index) {
if (index >= seq._atoms.size())
seq._atoms.resize(index + 1);
- return seq._atoms[index];
+ return seq._atoms[index].get();
+ }
+};
+
+// Declare that an AtomRange is a yaml sequence.
+template <typename T> struct SequenceTraits<File::AtomRange<T> > {
+ static size_t size(IO &io, File::AtomRange<T> &seq) { return seq.size(); }
+ static T *&element(IO &io, File::AtomRange<T> &seq, size_t index) {
+ assert(io.outputting() && "AtomRange only used when outputting");
+ assert(index < seq.size() && "Out of range access");
+ return seq[index].get();
}
};
@@ -558,23 +568,29 @@ template <> struct MappingTraits<const lld::File *> {
const lld::File *denormalize(IO &io) { return this; }
- const AtomVector<lld::DefinedAtom> &defined() const override {
+ const AtomRange<lld::DefinedAtom> defined() const override {
return _noDefinedAtoms;
}
- const AtomVector<lld::UndefinedAtom> &undefined() const override {
+ const AtomRange<lld::UndefinedAtom> undefined() const override {
return _noUndefinedAtoms;
}
- const AtomVector<lld::SharedLibraryAtom> &
- sharedLibrary() const override {
+ const AtomRange<lld::SharedLibraryAtom> sharedLibrary() const override {
return _noSharedLibraryAtoms;
}
- const AtomVector<lld::AbsoluteAtom> &absolute() const override {
+ const AtomRange<lld::AbsoluteAtom> absolute() const override {
return _noAbsoluteAtoms;
}
+ void clearAtoms() override {
+ _noDefinedAtoms.clear();
+ _noUndefinedAtoms.clear();
+ _noSharedLibraryAtoms.clear();
+ _noAbsoluteAtoms.clear();
+ }
+
File *find(StringRef name, bool dataSymbolOnly) override {
for (const ArchMember &member : _members) {
for (const lld::DefinedAtom *atom : member._content->defined()) {
@@ -606,36 +622,46 @@ template <> struct MappingTraits<const lld::File *> {
class NormalizedFile : public lld::File {
public:
NormalizedFile(IO &io)
- : File("", kindNormalizedObject), _io(io), _rnb(nullptr) {}
+ : File("", kindNormalizedObject), _io(io), _rnb(nullptr),
+ _definedAtomsRef(_definedAtoms._atoms),
+ _undefinedAtomsRef(_undefinedAtoms._atoms),
+ _sharedLibraryAtomsRef(_sharedLibraryAtoms._atoms),
+ _absoluteAtomsRef(_absoluteAtoms._atoms) {}
NormalizedFile(IO &io, const lld::File *file)
: File(file->path(), kindNormalizedObject), _io(io),
- _rnb(new RefNameBuilder(*file)), _path(file->path()) {
- for (const lld::DefinedAtom *a : file->defined())
- _definedAtoms._atoms.push_back(a);
- for (const lld::UndefinedAtom *a : file->undefined())
- _undefinedAtoms._atoms.push_back(a);
- for (const lld::SharedLibraryAtom *a : file->sharedLibrary())
- _sharedLibraryAtoms._atoms.push_back(a);
- for (const lld::AbsoluteAtom *a : file->absolute())
- _absoluteAtoms._atoms.push_back(a);
+ _rnb(new RefNameBuilder(*file)), _path(file->path()),
+ _definedAtomsRef(file->defined()),
+ _undefinedAtomsRef(file->undefined()),
+ _sharedLibraryAtomsRef(file->sharedLibrary()),
+ _absoluteAtomsRef(file->absolute()) {
+ }
+
+ ~NormalizedFile() override {
}
+
const lld::File *denormalize(IO &io);
- const AtomVector<lld::DefinedAtom> &defined() const override {
- return _definedAtoms._atoms;
+ const AtomRange<lld::DefinedAtom> defined() const override {
+ return _definedAtomsRef;
}
- const AtomVector<lld::UndefinedAtom> &undefined() const override {
- return _undefinedAtoms._atoms;
+ const AtomRange<lld::UndefinedAtom> undefined() const override {
+ return _undefinedAtomsRef;
}
- const AtomVector<lld::SharedLibraryAtom> &
- sharedLibrary() const override {
- return _sharedLibraryAtoms._atoms;
+ const AtomRange<lld::SharedLibraryAtom> sharedLibrary() const override {
+ return _sharedLibraryAtomsRef;
}
- const AtomVector<lld::AbsoluteAtom> &absolute() const override {
- return _absoluteAtoms._atoms;
+ const AtomRange<lld::AbsoluteAtom> absolute() const override {
+ return _absoluteAtomsRef;
+ }
+
+ void clearAtoms() override {
+ _definedAtoms._atoms.clear();
+ _undefinedAtoms._atoms.clear();
+ _sharedLibraryAtoms._atoms.clear();
+ _absoluteAtoms._atoms.clear();
}
// Allocate a new copy of this string in _storage, so the strings
@@ -653,6 +679,10 @@ template <> struct MappingTraits<const lld::File *> {
AtomList<lld::UndefinedAtom> _undefinedAtoms;
AtomList<lld::SharedLibraryAtom> _sharedLibraryAtoms;
AtomList<lld::AbsoluteAtom> _absoluteAtoms;
+ AtomRange<lld::DefinedAtom> _definedAtomsRef;
+ AtomRange<lld::UndefinedAtom> _undefinedAtomsRef;
+ AtomRange<lld::SharedLibraryAtom> _sharedLibraryAtomsRef;
+ AtomRange<lld::AbsoluteAtom> _absoluteAtomsRef;
llvm::BumpPtrAllocator _storage;
};
@@ -676,10 +706,18 @@ template <> struct MappingTraits<const lld::File *> {
info->_file = keys.operator->();
io.mapOptional("path", keys->_path);
- io.mapOptional("defined-atoms", keys->_definedAtoms);
- io.mapOptional("undefined-atoms", keys->_undefinedAtoms);
- io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtoms);
- io.mapOptional("absolute-atoms", keys->_absoluteAtoms);
+
+ if (io.outputting()) {
+ io.mapOptional("defined-atoms", keys->_definedAtomsRef);
+ io.mapOptional("undefined-atoms", keys->_undefinedAtomsRef);
+ io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtomsRef);
+ io.mapOptional("absolute-atoms", keys->_absoluteAtomsRef);
+ } else {
+ io.mapOptional("defined-atoms", keys->_definedAtoms);
+ io.mapOptional("undefined-atoms", keys->_undefinedAtoms);
+ io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtoms);
+ io.mapOptional("absolute-atoms", keys->_absoluteAtoms);
+ }
}
static void mappingArchive(IO &io, const lld::File *&file) {
@@ -790,6 +828,9 @@ template <> struct MappingTraits<const lld::DefinedAtom *> {
for (uint8_t x : cont)
_content.push_back(x);
}
+
+ ~NormalizedAtom() override = default;
+
const lld::DefinedAtom *denormalize(IO &io) {
YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
assert(info != nullptr);
@@ -938,6 +979,14 @@ template <> struct MappingTraits<const lld::DefinedAtom *> {
}
};
+template <> struct MappingTraits<lld::DefinedAtom *> {
+ static void mapping(IO &io, lld::DefinedAtom *&atom) {
+ const lld::DefinedAtom *atomPtr = atom;
+ MappingTraits<const lld::DefinedAtom *>::mapping(io, atomPtr);
+ atom = const_cast<lld::DefinedAtom *>(atomPtr);
+ }
+};
+
// YAML conversion for const lld::UndefinedAtom*
template <> struct MappingTraits<const lld::UndefinedAtom *> {
@@ -950,6 +999,8 @@ template <> struct MappingTraits<const lld::UndefinedAtom *> {
: _file(fileFromContext(io)), _name(atom->name()),
_canBeNull(atom->canBeNull()) {}
+ ~NormalizedAtom() override = default;
+
const lld::UndefinedAtom *denormalize(IO &io) {
YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
assert(info != nullptr);
@@ -993,6 +1044,14 @@ template <> struct MappingTraits<const lld::UndefinedAtom *> {
}
};
+template <> struct MappingTraits<lld::UndefinedAtom *> {
+ static void mapping(IO &io, lld::UndefinedAtom *&atom) {
+ const lld::UndefinedAtom *atomPtr = atom;
+ MappingTraits<const lld::UndefinedAtom *>::mapping(io, atomPtr);
+ atom = const_cast<lld::UndefinedAtom *>(atomPtr);
+ }
+};
+
// YAML conversion for const lld::SharedLibraryAtom*
template <> struct MappingTraits<const lld::SharedLibraryAtom *> {
@@ -1006,6 +1065,8 @@ template <> struct MappingTraits<const lld::SharedLibraryAtom *> {
_loadName(atom->loadName()), _canBeNull(atom->canBeNullAtRuntime()),
_type(atom->type()), _size(atom->size()) {}
+ ~NormalizedAtom() override = default;
+
const lld::SharedLibraryAtom *denormalize(IO &io) {
YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
assert(info != nullptr);
@@ -1061,6 +1122,14 @@ template <> struct MappingTraits<const lld::SharedLibraryAtom *> {
}
};
+template <> struct MappingTraits<lld::SharedLibraryAtom *> {
+ static void mapping(IO &io, lld::SharedLibraryAtom *&atom) {
+ const lld::SharedLibraryAtom *atomPtr = atom;
+ MappingTraits<const lld::SharedLibraryAtom *>::mapping(io, atomPtr);
+ atom = const_cast<lld::SharedLibraryAtom *>(atomPtr);
+ }
+};
+
// YAML conversion for const lld::AbsoluteAtom*
template <> struct MappingTraits<const lld::AbsoluteAtom *> {
@@ -1071,6 +1140,9 @@ template <> struct MappingTraits<const lld::AbsoluteAtom *> {
NormalizedAtom(IO &io, const lld::AbsoluteAtom *atom)
: _file(fileFromContext(io)), _name(atom->name()),
_scope(atom->scope()), _value(atom->value()) {}
+
+ ~NormalizedAtom() override = default;
+
const lld::AbsoluteAtom *denormalize(IO &io) {
YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
assert(info != nullptr);
@@ -1129,6 +1201,14 @@ template <> struct MappingTraits<const lld::AbsoluteAtom *> {
}
};
+template <> struct MappingTraits<lld::AbsoluteAtom *> {
+ static void mapping(IO &io, lld::AbsoluteAtom *&atom) {
+ const lld::AbsoluteAtom *atomPtr = atom;
+ MappingTraits<const lld::AbsoluteAtom *>::mapping(io, atomPtr);
+ atom = const_cast<lld::AbsoluteAtom *>(atomPtr);
+ }
+};
+
} // namespace llvm
} // namespace yaml
OpenPOWER on IntegriCloud