diff options
Diffstat (limited to 'lld/include')
-rw-r--r-- | lld/include/lld/Core/Atom.h | 51 | ||||
-rw-r--r-- | lld/include/lld/Core/DefinedAtom.h | 2 | ||||
-rw-r--r-- | lld/include/lld/Core/File.h | 99 | ||||
-rw-r--r-- | lld/include/lld/Core/Resolver.h | 13 | ||||
-rw-r--r-- | lld/include/lld/Core/SharedLibraryAtom.h | 2 | ||||
-rw-r--r-- | lld/include/lld/Core/SharedLibraryFile.h | 17 | ||||
-rw-r--r-- | lld/include/lld/Core/Simple.h | 59 | ||||
-rw-r--r-- | lld/include/lld/Core/UndefinedAtom.h | 2 |
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 |