1 //===- lld/Core/Simple.h - Simple implementations of Atom and File --------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 /// Provide simple implementations for Atoms and File.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLD_CORE_SIMPLE_H
15 #define LLD_CORE_SIMPLE_H
17 #include "lld/Core/AbsoluteAtom.h"
18 #include "lld/Core/Atom.h"
19 #include "lld/Core/DefinedAtom.h"
20 #include "lld/Core/File.h"
21 #include "lld/Core/Reference.h"
22 #include "lld/Core/SharedLibraryAtom.h"
23 #include "lld/Core/UndefinedAtom.h"
24 #include "llvm/ADT/SmallVector.h"
25 #include "llvm/ADT/StringRef.h"
26 #include "llvm/ADT/ilist.h"
27 #include "llvm/ADT/ilist_node.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,
115 public llvm::ilist_node<SimpleReference> {
117 SimpleReference(Reference::KindNamespace ns, Reference::KindArch arch,
118 Reference::KindValue value, uint64_t off, const Atom *t,
120 : Reference(ns, arch, value), _target(t), _offsetInAtom(off), _addend(a) {
123 : Reference(Reference::KindNamespace::all, Reference::KindArch::all, 0),
124 _target(nullptr), _offsetInAtom(0), _addend(0) {}
126 uint64_t offsetInAtom() const override { return _offsetInAtom; }
128 const Atom *target() const override {
133 Addend addend() const override { return _addend; }
134 void setAddend(Addend a) override { _addend = a; }
135 void setTarget(const Atom *newAtom) override { _target = newAtom; }
139 uint64_t _offsetInAtom;
143 class SimpleDefinedAtom : public DefinedAtom {
145 explicit SimpleDefinedAtom(const File &f)
146 : _file(f), _ordinal(f.getNextAtomOrdinalAndIncrement()) {}
148 ~SimpleDefinedAtom() override {
149 _references.clearAndLeakNodesUnsafely();
152 const File &file() const override { return _file; }
154 StringRef name() const override { return StringRef(); }
156 uint64_t ordinal() const override { return _ordinal; }
158 Scope scope() const override { return DefinedAtom::scopeLinkageUnit; }
160 Interposable interposable() const override {
161 return DefinedAtom::interposeNo;
164 Merge merge() const override { return DefinedAtom::mergeNo; }
166 Alignment alignment() const override { return 1; }
168 SectionChoice sectionChoice() const override {
169 return DefinedAtom::sectionBasedOnContent;
172 StringRef customSectionName() const override { return StringRef(); }
173 DeadStripKind deadStrip() const override {
174 return DefinedAtom::deadStripNormal;
177 DefinedAtom::reference_iterator begin() const override {
179 reinterpret_cast<const void *>(_references.begin().getNodePtr());
180 return reference_iterator(*this, it);
183 DefinedAtom::reference_iterator end() const override {
185 reinterpret_cast<const void *>(_references.end().getNodePtr());
186 return reference_iterator(*this, it);
189 const Reference *derefIterator(const void *it) const override {
190 return &*RefList::const_iterator(
191 *reinterpret_cast<const llvm::ilist_node<SimpleReference> *>(it));
194 void incrementIterator(const void *&it) const override {
195 RefList::const_iterator ref(
196 *reinterpret_cast<const llvm::ilist_node<SimpleReference> *>(it));
197 it = reinterpret_cast<const void *>(std::next(ref).getNodePtr());
200 void addReference(Reference::KindNamespace ns,
201 Reference::KindArch arch,
202 Reference::KindValue kindValue, uint64_t off,
203 const Atom *target, Reference::Addend a) override {
204 assert(target && "trying to create reference to nothing");
205 auto node = new (_file.allocator())
206 SimpleReference(ns, arch, kindValue, off, target, a);
207 _references.push_back(node);
210 /// Sort references in a canonical order (by offset, then by kind).
211 void sortReferences() const {
212 // Cannot sort a linked list, so move elements into a temporary vector,
213 // sort the vector, then reconstruct the list.
214 llvm::SmallVector<SimpleReference *, 16> elements;
215 for (SimpleReference &node : _references) {
216 elements.push_back(&node);
218 std::sort(elements.begin(), elements.end(),
219 [] (const SimpleReference *lhs, const SimpleReference *rhs) -> bool {
220 uint64_t lhsOffset = lhs->offsetInAtom();
221 uint64_t rhsOffset = rhs->offsetInAtom();
222 if (rhsOffset != lhsOffset)
223 return (lhsOffset < rhsOffset);
224 if (rhs->kindNamespace() != lhs->kindNamespace())
225 return (lhs->kindNamespace() < rhs->kindNamespace());
226 if (rhs->kindArch() != lhs->kindArch())
227 return (lhs->kindArch() < rhs->kindArch());
228 return (lhs->kindValue() < rhs->kindValue());
230 _references.clearAndLeakNodesUnsafely();
231 for (SimpleReference *node : elements) {
232 _references.push_back(node);
236 void setOrdinal(uint64_t ord) { _ordinal = ord; }
239 typedef llvm::ilist<SimpleReference> RefList;
243 mutable RefList _references;
246 class SimpleUndefinedAtom : public UndefinedAtom {
248 SimpleUndefinedAtom(const File &f, StringRef name) : _file(f), _name(name) {
249 assert(!name.empty() && "UndefinedAtoms must have a name");
252 ~SimpleUndefinedAtom() override = default;
254 /// file - returns the File that produced/owns this Atom
255 const File &file() const override { return _file; }
257 /// name - The name of the atom. For a function atom, it is the (mangled)
258 /// name of the function.
259 StringRef name() const override { return _name; }
261 CanBeNull canBeNull() const override { return UndefinedAtom::canBeNullNever; }
268 } // end namespace lld
270 #endif // LLD_CORE_SIMPLE_H