1 //===- lld/Core/Simple.h - Simple implementations of Atom and File --------===//
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// \brief Provide simple implementations for Atoms and File.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLD_CORE_SIMPLE_H
16 #define LLD_CORE_SIMPLE_H
18 #include "lld/Core/AbsoluteAtom.h"
19 #include "lld/Core/Atom.h"
20 #include "lld/Core/DefinedAtom.h"
21 #include "lld/Core/File.h"
22 #include "lld/Core/Reference.h"
23 #include "lld/Core/SharedLibraryAtom.h"
24 #include "lld/Core/UndefinedAtom.h"
25 #include "llvm/ADT/SmallVector.h"
26 #include "llvm/ADT/StringRef.h"
27 #include "llvm/ADT/ilist.h"
28 #include "llvm/Support/Allocator.h"
29 #include "llvm/Support/Casting.h"
30 #include "llvm/Support/ErrorHandling.h"
38 class SimpleFile : public File {
40 SimpleFile(StringRef path, File::Kind kind)
43 ~SimpleFile() override {
50 void addAtom(DefinedAtom &a) {
51 _defined.push_back(OwningAtomPtr<DefinedAtom>(&a));
53 void addAtom(UndefinedAtom &a) {
54 _undefined.push_back(OwningAtomPtr<UndefinedAtom>(&a));
56 void addAtom(SharedLibraryAtom &a) {
57 _shared.push_back(OwningAtomPtr<SharedLibraryAtom>(&a));
59 void addAtom(AbsoluteAtom &a) {
60 _absolute.push_back(OwningAtomPtr<AbsoluteAtom>(&a));
63 void addAtom(const Atom &atom) {
64 if (auto *p = dyn_cast<DefinedAtom>(&atom)) {
65 addAtom(const_cast<DefinedAtom &>(*p));
66 } else if (auto *p = dyn_cast<UndefinedAtom>(&atom)) {
67 addAtom(const_cast<UndefinedAtom &>(*p));
68 } else if (auto *p = dyn_cast<SharedLibraryAtom>(&atom)) {
69 addAtom(const_cast<SharedLibraryAtom &>(*p));
70 } else if (auto *p = dyn_cast<AbsoluteAtom>(&atom)) {
71 addAtom(const_cast<AbsoluteAtom &>(*p));
73 llvm_unreachable("atom has unknown definition kind");
77 void removeDefinedAtomsIf(std::function<bool(const DefinedAtom *)> pred) {
78 auto &atoms = _defined;
79 auto newEnd = std::remove_if(atoms.begin(), atoms.end(),
80 [&pred](OwningAtomPtr<DefinedAtom> &p) {
83 atoms.erase(newEnd, atoms.end());
86 const AtomRange<DefinedAtom> defined() const override { return _defined; }
88 const AtomRange<UndefinedAtom> undefined() const override {
92 const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
96 const AtomRange<AbsoluteAtom> absolute() const override {
100 void clearAtoms() override {
108 AtomVector<DefinedAtom> _defined;
109 AtomVector<UndefinedAtom> _undefined;
110 AtomVector<SharedLibraryAtom> _shared;
111 AtomVector<AbsoluteAtom> _absolute;
114 class SimpleReference : public Reference {
116 SimpleReference(Reference::KindNamespace ns, Reference::KindArch arch,
117 Reference::KindValue value, uint64_t off, const Atom *t,
119 : Reference(ns, arch, value), _target(t), _offsetInAtom(off), _addend(a),
120 _next(nullptr), _prev(nullptr) {
123 : Reference(Reference::KindNamespace::all, Reference::KindArch::all, 0),
124 _target(nullptr), _offsetInAtom(0), _addend(0), _next(nullptr),
128 uint64_t offsetInAtom() const override { return _offsetInAtom; }
130 const Atom *target() const override {
135 Addend addend() const override { return _addend; }
136 void setAddend(Addend a) override { _addend = a; }
137 void setTarget(const Atom *newAtom) override { _target = newAtom; }
138 SimpleReference *getNext() const { return _next; }
139 SimpleReference *getPrev() const { return _prev; }
140 void setNext(SimpleReference *n) { _next = n; }
141 void setPrev(SimpleReference *p) { _prev = p; }
145 uint64_t _offsetInAtom;
147 SimpleReference *_next;
148 SimpleReference *_prev;
151 } // end namespace lld
153 // ilist will lazily create a sentinal (so end() can return a node past the
154 // end of the list). We need this trait so that the sentinal is allocated
155 // via the BumpPtrAllocator.
159 struct ilist_sentinel_traits<lld::SimpleReference> {
161 ilist_sentinel_traits() : _allocator(nullptr) { }
163 void setAllocator(llvm::BumpPtrAllocator *alloc) {
167 lld::SimpleReference *createSentinel() const {
168 return new (*_allocator) lld::SimpleReference();
171 static void destroySentinel(lld::SimpleReference*) {}
173 static lld::SimpleReference *provideInitialHead() { return nullptr; }
175 lld::SimpleReference *ensureHead(lld::SimpleReference *&head) const {
177 head = createSentinel();
178 noteHead(head, head);
179 ilist_traits<lld::SimpleReference>::setNext(head, nullptr);
182 return ilist_traits<lld::SimpleReference>::getPrev(head);
185 void noteHead(lld::SimpleReference *newHead,
186 lld::SimpleReference *sentinel) const {
187 ilist_traits<lld::SimpleReference>::setPrev(newHead, sentinel);
191 mutable llvm::BumpPtrAllocator *_allocator;
194 } // end namespace llvm
198 class SimpleDefinedAtom : public DefinedAtom {
200 explicit SimpleDefinedAtom(const File &f)
201 : _file(f), _ordinal(f.getNextAtomOrdinalAndIncrement()) {
202 _references.setAllocator(&f.allocator());
205 ~SimpleDefinedAtom() override {
206 _references.clearAndLeakNodesUnsafely();
209 const File &file() const override { return _file; }
211 StringRef name() const override { return StringRef(); }
213 uint64_t ordinal() const override { return _ordinal; }
215 Scope scope() const override { return DefinedAtom::scopeLinkageUnit; }
217 Interposable interposable() const override {
218 return DefinedAtom::interposeNo;
221 Merge merge() const override { return DefinedAtom::mergeNo; }
223 Alignment alignment() const override { return 1; }
225 SectionChoice sectionChoice() const override {
226 return DefinedAtom::sectionBasedOnContent;
229 StringRef customSectionName() const override { return StringRef(); }
230 DeadStripKind deadStrip() const override {
231 return DefinedAtom::deadStripNormal;
234 DefinedAtom::reference_iterator begin() const override {
235 const void *it = reinterpret_cast<const void *>(&*_references.begin());
236 return reference_iterator(*this, it);
239 DefinedAtom::reference_iterator end() const override {
240 const void *it = reinterpret_cast<const void *>(&*_references.end());
241 return reference_iterator(*this, it);
244 const Reference *derefIterator(const void *it) const override {
245 return reinterpret_cast<const Reference*>(it);
248 void incrementIterator(const void *&it) const override {
249 const SimpleReference* node = reinterpret_cast<const SimpleReference*>(it);
250 const SimpleReference* next = node->getNext();
251 it = reinterpret_cast<const void*>(next);
254 void addReference(Reference::KindNamespace ns,
255 Reference::KindArch arch,
256 Reference::KindValue kindValue, uint64_t off,
257 const Atom *target, Reference::Addend a) override {
258 assert(target && "trying to create reference to nothing");
259 auto node = new (_file.allocator())
260 SimpleReference(ns, arch, kindValue, off, target, a);
261 _references.push_back(node);
264 /// Sort references in a canonical order (by offset, then by kind).
265 void sortReferences() const {
266 // Cannot sort a linked list, so move elements into a temporary vector,
267 // sort the vector, then reconstruct the list.
268 llvm::SmallVector<SimpleReference *, 16> elements;
269 for (SimpleReference &node : _references) {
270 elements.push_back(&node);
272 std::sort(elements.begin(), elements.end(),
273 [] (const SimpleReference *lhs, const SimpleReference *rhs) -> bool {
274 uint64_t lhsOffset = lhs->offsetInAtom();
275 uint64_t rhsOffset = rhs->offsetInAtom();
276 if (rhsOffset != lhsOffset)
277 return (lhsOffset < rhsOffset);
278 if (rhs->kindNamespace() != lhs->kindNamespace())
279 return (lhs->kindNamespace() < rhs->kindNamespace());
280 if (rhs->kindArch() != lhs->kindArch())
281 return (lhs->kindArch() < rhs->kindArch());
282 return (lhs->kindValue() < rhs->kindValue());
284 _references.clearAndLeakNodesUnsafely();
285 for (SimpleReference *node : elements) {
286 _references.push_back(node);
290 void setOrdinal(uint64_t ord) { _ordinal = ord; }
293 typedef llvm::ilist<SimpleReference> RefList;
297 mutable RefList _references;
300 class SimpleUndefinedAtom : public UndefinedAtom {
302 SimpleUndefinedAtom(const File &f, StringRef name) : _file(f), _name(name) {
303 assert(!name.empty() && "UndefinedAtoms must have a name");
306 ~SimpleUndefinedAtom() override = default;
308 /// file - returns the File that produced/owns this Atom
309 const File &file() const override { return _file; }
311 /// name - The name of the atom. For a function atom, it is the (mangled)
312 /// name of the function.
313 StringRef name() const override { return _name; }
315 CanBeNull canBeNull() const override { return UndefinedAtom::canBeNullNever; }
322 } // end namespace lld
324 #endif // LLD_CORE_SIMPLE_H