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/ADT/ilist_node.h"
29 #include "llvm/Support/Allocator.h"
30 #include "llvm/Support/Casting.h"
31 #include "llvm/Support/ErrorHandling.h"
39 class SimpleFile : public File {
41 SimpleFile(StringRef path, File::Kind kind)
44 ~SimpleFile() override {
51 void addAtom(DefinedAtom &a) {
52 _defined.push_back(OwningAtomPtr<DefinedAtom>(&a));
54 void addAtom(UndefinedAtom &a) {
55 _undefined.push_back(OwningAtomPtr<UndefinedAtom>(&a));
57 void addAtom(SharedLibraryAtom &a) {
58 _shared.push_back(OwningAtomPtr<SharedLibraryAtom>(&a));
60 void addAtom(AbsoluteAtom &a) {
61 _absolute.push_back(OwningAtomPtr<AbsoluteAtom>(&a));
64 void addAtom(const Atom &atom) {
65 if (auto *p = dyn_cast<DefinedAtom>(&atom)) {
66 addAtom(const_cast<DefinedAtom &>(*p));
67 } else if (auto *p = dyn_cast<UndefinedAtom>(&atom)) {
68 addAtom(const_cast<UndefinedAtom &>(*p));
69 } else if (auto *p = dyn_cast<SharedLibraryAtom>(&atom)) {
70 addAtom(const_cast<SharedLibraryAtom &>(*p));
71 } else if (auto *p = dyn_cast<AbsoluteAtom>(&atom)) {
72 addAtom(const_cast<AbsoluteAtom &>(*p));
74 llvm_unreachable("atom has unknown definition kind");
78 void removeDefinedAtomsIf(std::function<bool(const DefinedAtom *)> pred) {
79 auto &atoms = _defined;
80 auto newEnd = std::remove_if(atoms.begin(), atoms.end(),
81 [&pred](OwningAtomPtr<DefinedAtom> &p) {
84 atoms.erase(newEnd, atoms.end());
87 const AtomRange<DefinedAtom> defined() const override { return _defined; }
89 const AtomRange<UndefinedAtom> undefined() const override {
93 const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
97 const AtomRange<AbsoluteAtom> absolute() const override {
101 void clearAtoms() override {
109 AtomVector<DefinedAtom> _defined;
110 AtomVector<UndefinedAtom> _undefined;
111 AtomVector<SharedLibraryAtom> _shared;
112 AtomVector<AbsoluteAtom> _absolute;
115 class SimpleReference : public Reference,
116 public llvm::ilist_node<SimpleReference> {
118 SimpleReference(Reference::KindNamespace ns, Reference::KindArch arch,
119 Reference::KindValue value, uint64_t off, const Atom *t,
121 : Reference(ns, arch, value), _target(t), _offsetInAtom(off), _addend(a) {
124 : Reference(Reference::KindNamespace::all, Reference::KindArch::all, 0),
125 _target(nullptr), _offsetInAtom(0), _addend(0) {}
127 uint64_t offsetInAtom() const override { return _offsetInAtom; }
129 const Atom *target() const override {
134 Addend addend() const override { return _addend; }
135 void setAddend(Addend a) override { _addend = a; }
136 void setTarget(const Atom *newAtom) override { _target = newAtom; }
140 uint64_t _offsetInAtom;
144 class SimpleDefinedAtom : public DefinedAtom {
146 explicit SimpleDefinedAtom(const File &f)
147 : _file(f), _ordinal(f.getNextAtomOrdinalAndIncrement()) {}
149 ~SimpleDefinedAtom() override {
150 _references.clearAndLeakNodesUnsafely();
153 const File &file() const override { return _file; }
155 StringRef name() const override { return StringRef(); }
157 uint64_t ordinal() const override { return _ordinal; }
159 Scope scope() const override { return DefinedAtom::scopeLinkageUnit; }
161 Interposable interposable() const override {
162 return DefinedAtom::interposeNo;
165 Merge merge() const override { return DefinedAtom::mergeNo; }
167 Alignment alignment() const override { return 1; }
169 SectionChoice sectionChoice() const override {
170 return DefinedAtom::sectionBasedOnContent;
173 StringRef customSectionName() const override { return StringRef(); }
174 DeadStripKind deadStrip() const override {
175 return DefinedAtom::deadStripNormal;
178 DefinedAtom::reference_iterator begin() const override {
180 reinterpret_cast<const void *>(_references.begin().getNodePtr());
181 return reference_iterator(*this, it);
184 DefinedAtom::reference_iterator end() const override {
186 reinterpret_cast<const void *>(_references.end().getNodePtr());
187 return reference_iterator(*this, it);
190 const Reference *derefIterator(const void *it) const override {
191 return &*RefList::const_iterator(
192 *reinterpret_cast<const llvm::ilist_node<SimpleReference> *>(it));
195 void incrementIterator(const void *&it) const override {
196 RefList::const_iterator ref(
197 *reinterpret_cast<const llvm::ilist_node<SimpleReference> *>(it));
198 it = reinterpret_cast<const void *>(std::next(ref).getNodePtr());
201 void addReference(Reference::KindNamespace ns,
202 Reference::KindArch arch,
203 Reference::KindValue kindValue, uint64_t off,
204 const Atom *target, Reference::Addend a) override {
205 assert(target && "trying to create reference to nothing");
206 auto node = new (_file.allocator())
207 SimpleReference(ns, arch, kindValue, off, target, a);
208 _references.push_back(node);
211 /// Sort references in a canonical order (by offset, then by kind).
212 void sortReferences() const {
213 // Cannot sort a linked list, so move elements into a temporary vector,
214 // sort the vector, then reconstruct the list.
215 llvm::SmallVector<SimpleReference *, 16> elements;
216 for (SimpleReference &node : _references) {
217 elements.push_back(&node);
219 std::sort(elements.begin(), elements.end(),
220 [] (const SimpleReference *lhs, const SimpleReference *rhs) -> bool {
221 uint64_t lhsOffset = lhs->offsetInAtom();
222 uint64_t rhsOffset = rhs->offsetInAtom();
223 if (rhsOffset != lhsOffset)
224 return (lhsOffset < rhsOffset);
225 if (rhs->kindNamespace() != lhs->kindNamespace())
226 return (lhs->kindNamespace() < rhs->kindNamespace());
227 if (rhs->kindArch() != lhs->kindArch())
228 return (lhs->kindArch() < rhs->kindArch());
229 return (lhs->kindValue() < rhs->kindValue());
231 _references.clearAndLeakNodesUnsafely();
232 for (SimpleReference *node : elements) {
233 _references.push_back(node);
237 void setOrdinal(uint64_t ord) { _ordinal = ord; }
240 typedef llvm::ilist<SimpleReference> RefList;
244 mutable RefList _references;
247 class SimpleUndefinedAtom : public UndefinedAtom {
249 SimpleUndefinedAtom(const File &f, StringRef name) : _file(f), _name(name) {
250 assert(!name.empty() && "UndefinedAtoms must have a name");
253 ~SimpleUndefinedAtom() override = default;
255 /// file - returns the File that produced/owns this Atom
256 const File &file() const override { return _file; }
258 /// name - The name of the atom. For a function atom, it is the (mangled)
259 /// name of the function.
260 StringRef name() const override { return _name; }
262 CanBeNull canBeNull() const override { return UndefinedAtom::canBeNullNever; }
269 } // end namespace lld
271 #endif // LLD_CORE_SIMPLE_H